// Path: src/main/java/de/jfschaefer/layeredgraphlayout/layout/Vector.java
// public class Vector {
//     public final double x;
//     public final double y;
// 
//     public Vector(double x, double y) {
//         this.x = x;
//         this.y = y;
//     }
// 
//     public Vector scaled(double l) {
//         return new Vector(l * x, l * y);
//     }
// 
//     public Vector add(Vector other) {
//         return new Vector(this.x + other.x, this.y + other.y);
//     }
// }
// 
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/util/Pair.java
// public class Pair<A, B> {
//     public final A first;
//     public final B second;
//     public Pair(A first, B second) {
//         this.first = first;
//         this.second = second;
//     }
// }


import de.jfschaefer.layeredgraphlayout.layout.*;
import de.jfschaefer.layeredgraphlayout.layout.Vector;
import de.jfschaefer.layeredgraphlayout.util.Pair;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.CubicCurve;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import java.util.*;
        this.labelMap = labelMap;
        this.color = color;
    }

    public Node getEdgeVisualization(E edge, ArrayList<EdgeSegment> segments) {
        Group g = new Group();

        // Step 1: Line
        for (EdgeSegment segment : segments) {
            if (segment.isBezier()) {
                CubicCurve curve = new CubicCurve(segment.getStart().x, segment.getStart().y,
                        segment.getControl1().x, segment.getControl1().y,
                        segment.getControl2().x, segment.getControl2().y,
                        segment.getEnd().x, segment.getEnd().y);
                curve.setFill(Color.TRANSPARENT);
                curve.setStroke(color);
                g.getChildren().add(curve);
            } else {
                Line line = new Line(segment.getStart().x, segment.getStart().y,
                        segment.getEnd().x, segment.getEnd().y);
                line.setStroke(color);
                g.getChildren().add(line);
            }
        }

        // Step 2: Arrow head
        if (layoutConfig.getArrowheads()) {
            Polygon arrowhead = new Polygon(0d, 0d, 4d, 8d, 0d, 4d, -4d, 8d);
            EdgeSegment segment = segments.get(segments.size() - 1);
            double fraction = 1d;
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/layout/Vector.java
// public class Vector {
//     public final double x;
//     public final double y;
// 
//     public Vector(double x, double y) {
//         this.x = x;
//         this.y = y;
//     }
// 
//     public Vector scaled(double l) {
//         return new Vector(l * x, l * y);
//     }
// 
//     public Vector add(Vector other) {
//         return new Vector(this.x + other.x, this.y + other.y);
//     }
// }
// 
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/util/Pair.java
// public class Pair<A, B> {
//     public final A first;
//     public final B second;
//     public Pair(A first, B second) {
//         this.first = first;
//         this.second = second;
//     }
// }


// Path: src/main/java/de/jfschaefer/layeredgraphlayout/visualizationfx/SimpleGraphFXEdgeFactory.java
import de.jfschaefer.layeredgraphlayout.layout.*;
import de.jfschaefer.layeredgraphlayout.layout.Vector;
import de.jfschaefer.layeredgraphlayout.util.Pair;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.CubicCurve;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import java.util.*;

        this.labelMap = labelMap;
        this.color = color;
    }

    public Node getEdgeVisualization(E edge, ArrayList<EdgeSegment> segments) {
        Group g = new Group();

        // Step 1: Line
        for (EdgeSegment segment : segments) {
            if (segment.isBezier()) {
                CubicCurve curve = new CubicCurve(segment.getStart().x, segment.getStart().y,
                        segment.getControl1().x, segment.getControl1().y,
                        segment.getControl2().x, segment.getControl2().y,
                        segment.getEnd().x, segment.getEnd().y);
                curve.setFill(Color.TRANSPARENT);
                curve.setStroke(color);
                g.getChildren().add(curve);
            } else {
                Line line = new Line(segment.getStart().x, segment.getStart().y,
                        segment.getEnd().x, segment.getEnd().y);
                line.setStroke(color);
                g.getChildren().add(line);
            }
        }

        // Step 2: Arrow head
        if (layoutConfig.getArrowheads()) {
            Polygon arrowhead = new Polygon(0d, 0d, 4d, 8d, 0d, 4d, -4d, 8d);
            EdgeSegment segment = segments.get(segments.size() - 1);
            double fraction = 1d;
            Vector derivative = segment.getDerivativeAt(fraction);