zoom in/out a canvas on center



  • I'm trying to do an app where I can add some points around an image. I have done the basic, load an image and add a canvas. When press the space key I set the canvas position.

    I want the canvas to be always the same size when I resize the image. My problem is that my canvas doesn't look to be on the correct position when zoom in/zoom out. It looks like I'm doing some mistake and not move it around the center.

    alt text
    |
    | zooming in
    v
    alt text

    vice-versa

    alt text

    |
    | zooming out
    v

    alt text

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    import QtQuick.Window 2.1
    
    Rectangle {
        width: 500
        height: 500
        color: "gray"
    
        Flickable {
            id: flick
            anchors.fill: parent
            contentWidth: 500
            contentHeight: 500
    
            PinchArea {
                width: Math.max(flick.contentWidth, flick.width)
                height: Math.max(flick.contentHeight, flick.height)
    
                property real initialWidth
                property real initialHeight
                property real initialTesteX
                property real initialTesteY
                onPinchStarted: {
                    initialWidth = flick.contentWidth
                    initialHeight = flick.contentHeight
                    initialTesteX = marker.canvasX
                    initialTesteY = marker.canvasY
                }
    
                onPinchUpdated: {
                    // adjust content pos due to drag
                    flick.contentX += pinch.previousCenter.x - pinch.center.x
                    flick.contentY += pinch.previousCenter.y - pinch.center.y
    
                    // resize content
                    flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
                    marker.canvasX = initialTesteX*(pinch.scale)
                    marker.canvasY = initialTesteY*(pinch.scale)
    
                }
    
                onPinchFinished: {
                    // Move its content within bounds.
                    flick.returnToBounds()
                }
    
                Canvas {
                    id: marker
                    anchors {
                        top: parent.top
                        left: parent.left
                        margins: 4
                    }
                    z: 100
                    property real canvasX: 341
                    property real canvasY: 330
    
                    width: flick.contentWidth
                    height: flick.contentHeight
    
                    antialiasing: true
                    transformOrigin: Item.TopLeft
    
                    onPaint: {
                        var ctx = getContext( "2d" );
                        ctx.save();
                        ctx.clearRect( 0, 0, width, height );
                        ctx.lineWidth = 2;
                        ctx.beginPath();
                        ctx.strokeStyle = "blue"
                        ctx.arc(canvasX,
                                canvasY,
                                6,
                                0,
                                Math.PI * 2 );
                        ctx.stroke();
                        ctx.restore();
                    }
                }
    
                Rectangle {
                    id: image
                    width: flick.contentWidth
                    height: flick.contentHeight
                    color: "white"
                    Image {
                        anchors.fill: parent
                        source: "grid.png"
                        MouseArea {
    
                            focus: true
                            hoverEnabled: true
                            Keys.onPressed: {
                                if ( event.key === Qt.Key_Space ) {
                                    console.log("Space");
                                    marker.canvasX = mouseX-6
                                    marker.canvasY = mouseY-6
                                    console.log(mouseX)
                                    console.log(mouseY)
                                    marker.requestPaint()
                                    event.accepted = true
                                }
                            }
    
                            anchors.fill: parent
                            onDoubleClicked: {
                                //flick.contentWidth = 500
                                //flick.contentHeight = 500
                                //marker.canvasX = 341
                                //marker.canvasY = 330
                            }
                            onClicked: {
                                //marker.canvasX = mouseX-6
                                //marker.canvasY = mouseY-6
                                //marker.requestPaint()
                                console.log(mouseX)
                                console.log(mouseY)
                            }
                            onPositionChanged: {
                                console.log(mouseX)
                                console.log(mouseY)
                            }
                        }
    
                    }
                }
    
            }
        }
    }
    

    Can you guide me on how to do this the right way?



  • Can anyone take a look and give me some hint on my problem? Thank you very much!


  • Qt Champions 2016

    I'm no QML guru (or even a proper user) but this one I find rather dubious:

    flick.contentX += pinch.previousCenter.x - pinch.center.x
    flick.contentY += pinch.previousCenter.y - pinch.center.y
    

    Can you reduce the number of additions (and subtractions)? You're probably accumulating a mighty floating point error here by just getting the offset and moving the content by small additions. If not, at least use an algorithm that's more numerically stable than this, e.g. kahan summation.

    PS
    You could also take a peek here for some more considerations

    PS 2
    Also additional thing to consider is catastrophic cancellation in the subtraction, albeit it shouldn't happen. So one can as first step rephrase the expressions like:

    previousCenters += pinch.previousCenter.x
    centers += pinch.center.x
    
    flick.contentX = previousCenters - centers // Only here do the subtraction
    

    And additionally look up for the treatment of the actual summing.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.