2
votes

I have a problem to manipulate an Arc shape in javafx with mouse drag events

I have an Arc defined with the following paramters:

  • radiusX and radiusY :horizontal and vertical radius of the full ellipse of which this arc is a partial section
  • centerX,centerY : center point of the Arc
  • startAngle: starting angle of the arc (relative to the horizontal axis)
  • length: angular extent of the arc in degrees

So what i need is to make the start angle of the arc "follow" the mouse movement while dragging:

when the user press on the starting point of the Arc (located on the startAngle) and while dragging the mouse i need to compute the new starting angle formed by the horizontal axis and the line from the center to the mouse position

Basically the problem is to compute the start angle of the arc given a point (the mouse position) and the other given parameters (center, major and minor axis)

What i'm doing actuyally is calculating the angle with the Math.atan2 function

newStartAngle = atan2(xMouse, yMouse) (assume center x, y at 0,0)

but it works only if the arc is circular (radiusX = radiusY)

Another way to put it is : i need the start point of the arc to be always on the line from the center to the mouse position (so i need to continually update the start angle in order to make it follow the mouse rotation movement). (i hope i've made it a little clear)

Here is the complete source of a sample

import javafx.stage.Stage;
...

public class Main extends Application {

@Override
public void start(Stage primaryStage) {
    Pane pane = new Pane();

    Group designer = createDesigner();
    designer.setLayoutX(100);
    designer.setLayoutY(200);
    pane.getChildren().add(designer);

    Scene sc = new Scene(pane, 600, 600);
    primaryStage.setScene(sc);
    primaryStage.show();
}

public static final double RX = 100;
public static final double RY = 50;
public static final double S_ANGLE = 45;
public static final double ARC_LENGTH = 90;

private Arc arc;
private Circle handle;
private Line connection;
double xMouse,yMouse;

public Group createDesigner() {

    arc = new Arc();        
    arc.setRadiusX(RX);
    arc.setRadiusY(RY); 
    arc.setStartAngle(S_ANGLE);
    arc.setLength(ARC_LENGTH);
    arc.setFill(Color.LIGHTBLUE);
    arc.setType(ArcType.ROUND);

    handle = new Circle();
    handle.setRadius(5);    
    handle.setStroke(Color.BLACK);
    handle.setFill(Color.TRANSPARENT);

    handle.setCenterX(
            RX * Math.cos(Math.toRadians(S_ANGLE))
        );
    handle.setCenterY(
            -RY * Math.cos(Math.toRadians(S_ANGLE))
        );

    connection = new Line();
    connection.startXProperty().bind(arc.centerXProperty());
    connection.startYProperty().bind(arc.centerYProperty());
    connection.endXProperty().bind(handle.centerXProperty());
    connection.endYProperty().bind(handle.centerYProperty());

    handle.setOnMouseDragged(new EventHandler<MouseEvent>() {

        @Override
        public void handle(MouseEvent event) {

            xMouse = event.getX();
            yMouse = event.getY();

            handle.setCenterX(xMouse);
            handle.setCenterY(yMouse);


           double angleInRadians = Math.atan2(-yMouse, xMouse);

            arc.setStartAngle(Math.toDegrees(angleInRadians));

        }

    });

    return new Group(arc, connection, handle);

}

public static void main(String[] args) {
    launch(args);
}

}

Thank you in advance

1

1 Answers

2
votes

well i solved it, suffice to divide xMouse and yMouse by major and minor axe to make it work

newStartAngle = Math.atan2(-yMouse/radiusY, xMouse/radiusX) 
//assume center x, y at 0,0