2016-11-15 3 views
0

Ich habe diesen Teil meines Code:JavaFX - Extras horizontaler Raum in Zeichnung Pfeilen nach der Drehung

Group g = new Group(); 

double xMid = (end.getCenterX() - start.getCenterX())/2; 
double yMid = (end.getCenterY() - start.getCenterY())/2; 
Line a = new Line(xMid, yMid-4, xMid, yMid+4); 
Line b = new Line(xMid, yMid-4, xMid-10, yMid); 
Line c = new Line(xMid, yMid+4, xMid-10, yMid); 

g.getChildren().add(a); 
g.getChildren().add(b); 
g.getChildren().add(c); 

g.setRotate(getAngle(start, end)); 
g.setTranslateX(start.getCenterX()); 
g.setTranslateY(start.getCenterY()); 

Der obige Code ist für einen Pfeil in der Mitte einer Linie zu zeichnen, die von start zu end geht (Dies sind Circle s als Start- und Endpunkt). Der Pfeil muss in die richtige Richtung gedreht werden. Hier ist die Ausgabe für mehrere Zeilen mit solchen Pfeile:

output

Wie Sie sehen können, gibt es eine Verschiebung nach links, wenn Winkel nahe 90 ° bis ±.

ich read dass:

[...], wenn Transformationen und Effekte direkt auf Kinder dieser Gruppe festgelegt sind, werden diejenigen, die in diesem Layoutgrenzen des Konzerns einbezogen werden.

aber es hat mir nicht wirklich geholfen, dieses Problem zu lösen. Hast du irgendwelche Ideen, wie das zu beheben ist?

+0

Ich bin verwirrt, was ist die Übersetzung am Ende? Sind Sie sicher, dass die Pfeile nicht von Ende zu Anfang zeigen? Was die Schicht betrifft, haben Sie sich die LayoutBounds angeschaut? Der Drehpunkt der Drehung ist das Zentrum der LayoutBounds, wenn das also nicht die Mitte des Dreiecks ist, könnte das die Verschiebung erklären. – Lidae

+0

@Lidae Pfeil wird gedreht und dann an die richtige Stelle verschoben - Mitte der Linie. Daher die Übersetzung. – alex

+0

aber sie sind schon vor der Übersetzung an der richtigen Stelle, es sei denn die Pfeile zeigen nach innen, aber dann zeigt der Pfeilkopf in die falsche Richtung ... – Lidae

Antwort

1

Zunächst alle drei Linien, die ein Dreieck bilden, sind am einfachsten zu Verwenden Sie Polygon.

Um den Drehpunkt fix auf der Grundlage der Layoutgrenzen gewählt werden, damit sie eine Rotate Transformation und eine Translate Transformation als transform s oder einfach berechnen verwenden könnte Verkettung der zwei Matrizen auf eigene Faust und verwenden Affine:

private static final double[] POLYGON_POINTS = { 
    -5, -4, 
    -5, 4, 
    5, 0 
}; 

private static void makeArrow(Pane parent, Circle start, Circle end, double t) { 
    Polygon arrow = new Polygon(POLYGON_POINTS); 
    arrow.setFill(null); 
    arrow.setStroke(Color.BLACK); 
    double dx = end.getCenterX() - start.getCenterX(); 
    double dy = end.getCenterY() - start.getCenterY(); 

    double d = Math.hypot(dx, dy); 

    double sin = dy/d; 
    double cos = dx/d; 

    // matrix: 
    // [ cos  -sin  0 t * dx + start.getCenterX() ]   
    // [ sin  cos  0 t * dy + start.getCenterY() ]   
    // [ 0  0  1     0   ]   
    // [ 0  0  0     1   ] 
    Affine affine = new Affine(cos, -sin, t * dx + start.getCenterX(), sin, cos, t * dy + start.getCenterY()); 

    arrow.getTransforms().add(affine); 
    parent.getChildren().add(arrow); 
} 

@Override 
public void start(Stage primaryStage) { 
    Circle end = new Circle(200, 20, 5); 
    Circle start = new Circle(20, 200, 5); 
    Line line = new Line(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY()); 

    Pane root = new Pane(line, start, end); 

    makeArrow(root, start, end, 0.5); 

    Scene scene = new Scene(root, 400, 400); 

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

Schön und einfach. Vielen Dank! – alex

0

Ich denke, es ist einfacher, eine Gruppe zu erstellen, die eine Aufwärtslinie und einen Pfeil zusammen enthält, und diese Gruppe dann einfach um die Mitte zu drehen.

public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      Pane root = createPane(); 
      root.setTranslateX(200); 
      root.setTranslateY(200); 
      Scene scene = new Scene(root,400,400); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private Pane createPane() { 
     BorderPane root = new BorderPane(); 
     ArrowFactory arrowfactory = new ArrowFactory(); 
     double lineLength = 100; 
     double centerX = 0; 
     double centerY = 0; 
     root.getChildren().addAll(
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 0), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 30), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 45), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 60), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 90), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 135), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 180), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 225), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 270), 
      arrowfactory.createLineAndArrow(centerX, centerY, lineLength, 315) 
      ); 
     return root; 
    } 

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

} 

ArrayFactory.java:

public class ArrowFactory { 
    private final int arrowWidth = 10; 
    private final int arrowHeight = 10; 

    public Group createLineAndArrow(double centerX, double centerY, double lineLength, double rotation) { 
     Group group = new Group(); 

     Line line = new Line(centerX, centerY, centerX, centerY - lineLength); 
     Polygon upwardArrow = createUpwardArrow(centerX, centerY - lineLength/2); 

     group.getChildren().addAll(line, upwardArrow); 
     group.getTransforms().add(new Rotate(rotation, centerX, centerY)); 
     return group; 
    } 

    private Polygon createUpwardArrow(double centerX, double centerY) { 
     Polygon arrow = new Polygon(
       createUpwardArrowPoints(centerX, centerY + arrowHeight/2)); 
     arrow.setFill(Color.TRANSPARENT); 
     arrow.setStroke(Color.BLACK); 
     return arrow; 
    } 

    private double[] createUpwardArrowPoints(double centerX, double centerY) { 
     return new double[] { 
      centerX - arrowWidth/2, centerY, // left 
      centerX + arrowWidth/2, centerY, // right 
      centerX, centerY - arrowHeight,  // top 
       }; 
    } 
} 

enter image description here

für Kreismittel als Eingaben verwenden Sie könnten verwenden:

private Group createLineAndArrow(double x1, double y1, double x2, double y2) { 
     double distance = Math.hypot(x1-x2, y1-y2); 
     double angle = Math.toDegrees(Math.atan2(x2 - x1, y2 - y1)); 
     return arrowfactory.createLineAndArrow(x1, y1, distance, angle); 
} 
Verwandte Themen