-1

I have a JavaFx ArcTo which connects two Vertices. The intent is to draw the directed edges on a graph, where two Vertices could share opposite-facing directed edges. The arc is to avoid overlap and make sure both edges are visible. Setting the radius of x and y is easy enough, but I want the arc to remain visually consistent no matter what the arc's orientation is within the parent node, which in this case is an AnchorPane. I have access to the (x,y) positions of both vertices.

I need the arc to have the same sort of flattened appearance no matter its orientation. I'm also open to solutions that don't involve the arcTo.

Here is an image of the desired behavior. Thank you for any help! :) enter image description here

paullc
  • 27
  • 6

1 Answers1

0

To keep the ratio of the distance of the furthest point on the arc to the line connecting it's ends to the distance of the ends the same, simply scale the radii linear with the distance of the ends. The following code allows you to move one of the end points by clicking on the scene. However there's no logic needed other than updating the end points to accomodate for changed orientation at all; The only relevant change is the change in distance.

@Override
public void start(Stage primaryStage) throws Exception {
    ArcTo arc1 = new ArcTo();
    arc1.setLargeArcFlag(false);

    ArcTo arc2 = new ArcTo();
    arc2.setLargeArcFlag(false);

    Path path = new Path(new MoveTo(400, 400), arc1, arc2);
    path.setFill(null);
    path.setStroke(Color.BLACK);

    Pane root = new Pane(path);
    root.setOnMouseClicked(evt -> updateArcs(arc1, arc2, 400, 400, evt.getX(), evt.getY()));
    Scene scene = new Scene(root, 800, 800);

    updateArcs(arc1, arc2, 400, 400, 600, 200);

    primaryStage.setScene(scene);
    primaryStage.show();
}

private static void updateArcs(ArcTo arc1, ArcTo arc2, double startX, double startY, double endX, double endY) {
    final double factor = 0.8;

    arc1.setX(endX);
    arc1.setY(endY);

    arc2.setX(startX);
    arc2.setY(startY);

    double radius = factor * Math.hypot(endX - startX, endY - startY);
    arc1.setRadiusX(radius);
    arc1.setRadiusY(radius);

    arc2.setRadiusX(radius);
    arc2.setRadiusY(radius);
}
fabian
  • 80,457
  • 12
  • 86
  • 114
  • Hello. I tried this and it works for two nodes connected by one edge but I have an arbitrary number of these nodes on the graph moving around, with each edge initialized to a different node's coordinates. Is there any way I could bind the radiusX and Y properties to the hypotenuse? I tried generating a binding for it from the coordinates of the two nodes but I get stuck at taking the square root of two bindings. – paullc May 28 '20 at 08:46
  • Sorry, disregard that last comment. I made a silly mistake :). Thank you for your solution. I got it to work and was able to get it to a point I'm proud of. What would your strategy be for adding a label at a point along the arc? – paullc May 28 '20 at 09:06
  • Depends on the desired behavior. Basically you can create a transformation transforming points of a coordinate system prior to the change to the system after the change by combining translation, rotation and scale. this should allow you to either transform the whole label or transform point(s) that allow you to calcualte the new position of the node. That's not entirely trivial though... – fabian May 28 '20 at 16:38