JavaFX - rotate canvas around specific X and Y

Galco :

I'm trying to draw an airplane on a canvas using SVGPath and move it based on an input of location and degree. I've managed to draw the airplane and move it correctly on the screen based on it location, but I can't figure how to rotate the plane correctly based on the angle.

This is what I have, I tested it with a button giving different angles but the plane stay the same:

public void redraw() {
    GraphicsContext gc = getGraphicsContext2D();
    String path = new String("M 323.193 226.645 c 39.244 24.41 75.644 47.053 115.706 71.978 c 7.687 -5.443 20.518 -14.485 33.308 -23.596 c 16.733 -11.923 36.27 -11.452 49.046 3.779 c 3.513 4.191 2.568 15.766 -0.705 21.426 c -23.705 40.994 -48.427 81.404 -73.095 121.833 c -4.729 7.745 -9.06 19.278 -21.177 13.509 c -12.203 -5.8 -28.746 -9.521 -27.842 -28.026 c 0.891 -18.185 3.495 -36.292 4.924 -50.249 c -40.704 -19.793 -79.74 -38.778 -119.825 -58.269 c -16.168 17.561 -22.275 40.532 -27.606 64.119 c -8.975 39.719 -18.474 79.324 -28.171 118.881 c -5.593 22.809 -12.452 26.109 -34.167 17.908 c -28.122 -10.606 -31.047 -14.689 -31.318 -45.384 c -0.605 -68.198 -1.514 -136.4 -1.325 -204.593 c 0.045 -15.865 -4.177 -25.531 -19.237 -32.95 c -30.238 -14.884 -60.119 -30.866 -88.548 -48.915 c -13.988 -8.884 -26.951 -21.77 -35.867 -35.727 C 3.526 110.834 15.381 90.43 40.637 91.746 c 17.786 0.931 36.644 4.67 52.618 12.229 c 32.58 15.413 63.735 33.905 95.022 51.921 c 8.735 5.028 15.083 4.992 23.944 0.068 c 64.671 -35.921 129.717 -71.172 194.611 -106.705 c 25.712 -14.075 46.608 -10.335 65.331 12.008 c 10.309 12.302 2.247 20.797 -6.506 28.579 c -35.89 31.91 -72.438 63.093 -107.682 95.687 C 344.877 197.641 334.677 212.878 323.193 226.645 Z");
    double wid = getWidth()/247;
    double hei = getHeight()/152;
    if(!isFirst) {
        gc.scale(50,50);
        gc.rotate(360-lastRotate);
        setTranslateX(-(lastX-48));
        setTranslateY(-(lastY-72));
        gc.setFill(Color.BLACK);
        gc.fill();
    }


    gc.clearRect(0, 0, getWidth(), getHeight());    
    if(!isFirst) {
        setTranslateX(x-48);
        setTranslateY(y-72);
    }
    gc.translate(wid*x, hei*y);
    gc.scale(0.02,0.02);    
    gc.rotate(rotate);
    gc.appendSVGPath(path);
    gc.setFill(Color.BLACK);
    gc.fill();

    gc.stroke();
    isFirst = false;
}

If I change it to this, then the plane rotates, but also moves (probably because the center of the rotation) which is unwanted. Any help would appreciated :

            if(!isFirst) {
        gc.scale(50,50);
        //gc.rotate(360-lastRotate);
        setTranslateX(-(lastX-48));
        setTranslateY(-(lastY-72));
        gc.setFill(Color.BLACK);
        gc.fill();
    }


    gc.clearRect(0, 0, getWidth(), getHeight());    
    if(!isFirst) {
        setTranslateX(x-48);
        setTranslateY(y-72);
    }
    gc.translate(wid*x, hei*y);
    gc.scale(0.02,0.02);    
    if(isFirst)
        gc.rotate(rotate);
    else
        setRotate(rotate);
    gc.appendSVGPath(path);
    gc.setFill(Color.BLACK);
    gc.fill();

    gc.stroke();
fabian :

I don't recommend undoing transformations "manually" by applying the inverse transformation. In addition to making the code hard to read, there may be rounding errors that may accumulate over time. Instead use save and restore to remove the transformation after you're done drawing.

As for determining a transformation with a pivot point: I recommend using Rotate for this purpose.

BTW: Don not use the String constructor taking a String parameter, unless you're sure this is absolutely necessary. Use the expression you would pass as parameter directly instead.

private double rotate;
private double x;
private double y;
private final Rotate rot = new Rotate(0, 50, 50); // modify the last 2 parameters to change the pivot point

public void redraw() {
    GraphicsContext gc = getGraphicsContext2D();
    String path = "M 323.193 226.645 c 39.244 24.41 75.644 47.053 115.706 71.978 c 7.687 -5.443 20.518 -14.485 33.308 -23.596 c 16.733 -11.923 36.27 -11.452 49.046 3.779 c 3.513 4.191 2.568 15.766 -0.705 21.426 c -23.705 40.994 -48.427 81.404 -73.095 121.833 c -4.729 7.745 -9.06 19.278 -21.177 13.509 c -12.203 -5.8 -28.746 -9.521 -27.842 -28.026 c 0.891 -18.185 3.495 -36.292 4.924 -50.249 c -40.704 -19.793 -79.74 -38.778 -119.825 -58.269 c -16.168 17.561 -22.275 40.532 -27.606 64.119 c -8.975 39.719 -18.474 79.324 -28.171 118.881 c -5.593 22.809 -12.452 26.109 -34.167 17.908 c -28.122 -10.606 -31.047 -14.689 -31.318 -45.384 c -0.605 -68.198 -1.514 -136.4 -1.325 -204.593 c 0.045 -15.865 -4.177 -25.531 -19.237 -32.95 c -30.238 -14.884 -60.119 -30.866 -88.548 -48.915 c -13.988 -8.884 -26.951 -21.77 -35.867 -35.727 C 3.526 110.834 15.381 90.43 40.637 91.746 c 17.786 0.931 36.644 4.67 52.618 12.229 c 32.58 15.413 63.735 33.905 95.022 51.921 c 8.735 5.028 15.083 4.992 23.944 0.068 c 64.671 -35.921 129.717 -71.172 194.611 -106.705 c 25.712 -14.075 46.608 -10.335 65.331 12.008 c 10.309 12.302 2.247 20.797 -6.506 28.579 c -35.89 31.91 -72.438 63.093 -107.682 95.687 C 344.877 197.641 334.677 212.878 323.193 226.645 Z";

    gc.clearRect(0, 0, getWidth(), getHeight());

    gc.save();

    gc.translate(x, y);
    gc.scale(0.02, 0.02);

    rot.setAngle(rotate);
    gc.transform(rot.getMxx(), rot.getMyx(), rot.getMxy(), rot.getMyy(), rot.getTx(), rot.getTy());

    gc.setFill(Color.BLACK);
    gc.beginPath();
    gc.appendSVGPath(path);
    gc.fill();
    gc.stroke();

    gc.restore(); // clear tranformation
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=122008&siteId=1