2016-08-08 59 views
0

對於簡單的線箭頭i寫了這個代碼:JavaFX的CubicCurve與角度和長度

double lineAngle = Math.atan2(startPosition.getY() - endPosition.getY(), startPosition.getX() - endPosition.getX()); 

    double arrowX1 = Math.cos(lineAngle + Math.toRadians(ARROW_ANGLE)) * ARROW_LENGTH + endPosition.getX(); 
    double arrowY1 = Math.sin(lineAngle + Math.toRadians(ARROW_ANGLE)) * ARROW_LENGTH + endPosition.getY(); 

    double arrowX2 = Math.cos(lineAngle - Math.toRadians(ARROW_ANGLE)) * ARROW_LENGTH + endPosition.getX(); 
    double arrowY2 = Math.sin(lineAngle - Math.toRadians(ARROW_ANGLE)) * ARROW_LENGTH + endPosition.getY(); 

    MoveTo leftArrowMove = new MoveTo(endPosition.getX(), endPosition.getY()); 
    LineTo leftArrowLine = new LineTo(arrowX1, arrowY1); 
    MoveTo rightArrowMove = new MoveTo(endPosition.getX(), endPosition.getY()); 
    LineTo rightArrowLine = new LineTo(arrowX2, arrowY2); 

    path.getElements().addAll(leftArrowMove, leftArrowLine, rightArrowMove, rightArrowLine); 

凡ARROW_ANGLE和ARROW_LENGTH是常數。

我怎樣才能做同樣的三次曲線? 我在這裏發現了一些三次曲線箭頭的樣本,但是我不能改變角度和長度。

public void start(Stage primaryStage) { 

    Group root = new Group(); 

    // bending curve 
    Rectangle srcRect1 = new Rectangle(100,100,50,50); 
    Rectangle dstRect1 = new Rectangle(300,300,50,50); 

    CubicCurve curve1 = new CubicCurve(125, 150, 125, 225, 325, 225, 325, 300); 
    curve1.setStroke(Color.BLACK); 
    curve1.setStrokeWidth(1); 
    curve1.setFill(null); 

    double size=Math.max(curve1.getBoundsInLocal().getWidth(), 
         curve1.getBoundsInLocal().getHeight()); 
    double scale=size/4d; 

    Point2D ori=eval(curve1,0); 
    Point2D tan=evalDt(curve1,0).normalize().multiply(scale); 
    Path arrowIni=new Path(); 
    arrowIni.getElements().add(new MoveTo(ori.getX()+0.2*tan.getX()-0.2*tan.getY(), 
             ori.getY()+0.2*tan.getY()+0.2*tan.getX())); 
    arrowIni.getElements().add(new LineTo(ori.getX(), ori.getY())); 
    arrowIni.getElements().add(new LineTo(ori.getX()+0.2*tan.getX()+0.2*tan.getY(), 
             ori.getY()+0.2*tan.getY()-0.2*tan.getX())); 

    ori=eval(curve1,1); 
    tan=evalDt(curve1,1).normalize().multiply(scale); 
    Path arrowEnd=new Path(); 
    arrowEnd.getElements().add(new MoveTo(ori.getX()-0.2*tan.getX()-0.2*tan.getY(), 
             ori.getY()-0.2*tan.getY()+0.2*tan.getX())); 
    arrowEnd.getElements().add(new LineTo(ori.getX(), ori.getY())); 
    arrowEnd.getElements().add(new LineTo(ori.getX()-0.2*tan.getX()+0.2*tan.getY(), 
             ori.getY()-0.2*tan.getY()-0.2*tan.getX())); 

    root.getChildren().addAll(srcRect1, dstRect1, curve1, arrowIni, arrowEnd); 

    primaryStage.setScene(new Scene(root, 800, 600)); 
    primaryStage.show(); 
} 

/** 
* Evaluate the cubic curve at a parameter 0<=t<=1, returns a Point2D 
* @param c the CubicCurve 
* @param t param between 0 and 1 
* @return a Point2D 
*/ 
private Point2D eval(CubicCurve c, float t){ 
    Point2D p=new Point2D(Math.pow(1-t,3)*c.getStartX()+ 
      3*t*Math.pow(1-t,2)*c.getControlX1()+ 
      3*(1-t)*t*t*c.getControlX2()+ 
      Math.pow(t, 3)*c.getEndX(), 
      Math.pow(1-t,3)*c.getStartY()+ 
      3*t*Math.pow(1-t, 2)*c.getControlY1()+ 
      3*(1-t)*t*t*c.getControlY2()+ 
      Math.pow(t, 3)*c.getEndY()); 
    return p; 
} 

/** 
* Evaluate the tangent of the cubic curve at a parameter 0<=t<=1, returns a Point2D 
* @param c the CubicCurve 
* @param t param between 0 and 1 
* @return a Point2D 
*/ 
private Point2D evalDt(CubicCurve c, float t){ 
    Point2D p=new Point2D(-3*Math.pow(1-t,2)*c.getStartX()+ 
      3*(Math.pow(1-t, 2)-2*t*(1-t))*c.getControlX1()+ 
      3*((1-t)*2*t-t*t)*c.getControlX2()+ 
      3*Math.pow(t, 2)*c.getEndX(), 
      -3*Math.pow(1-t,2)*c.getStartY()+ 
      3*(Math.pow(1-t, 2)-2*t*(1-t))*c.getControlY1()+ 
      3*((1-t)*2*t-t*t)*c.getControlY2()+ 
      3*Math.pow(t, 2)*c.getEndY()); 
    return p; 
} 
+0

你到底想幹什麼?在三次曲線的末端畫一個箭頭? –

回答

1

注意,evalevalDt方法是沒有必要在這裏。除了開始點和結束點,您不會評估任何地方,在這種情況下,起始點和結束點是eval方法的結果,evalDt方法的結果分別是control1 - startcontrol2 - end。也可以使用tan.angle(1, 0)(即,通過確定切向量與x軸之間的角度)來計算線角度。

此外,可以使用相對PathElement s,即使用相對於最後PathElement的終點的位置。這簡化了箭頭。

在下面的例子中,除了相對LineTo s的使用Rotate變換旋轉的切線:

@Override 
public void start(Stage primaryStage) { 
    Group root = new Group(); 

    // bending curve 
    Rectangle srcRect1 = new Rectangle(100, 100, 50, 50); 
    Rectangle dstRect1 = new Rectangle(300, 300, 50, 50); 

    CubicCurve curve1 = new CubicCurve(125, 150, 125, 225, 100, 325, 300, 325); 
    curve1.setStroke(Color.BLACK); 
    curve1.setStrokeWidth(1); 
    curve1.setFill(null); 

    final double ARROW_LENGTH = 15; 
    final double ARROW_ANGLE = 45; 

    // the transform for the rotation arrow rotation 
    Rotate rotation = new Rotate(ARROW_ANGLE); 

    // direction = inwards from the start point 
    Point2D tan = new Point2D(
      curve1.getControlX1() - curve1.getStartX(), 
      curve1.getControlY1() - curve1.getStartY() 
    ).normalize().multiply(ARROW_LENGTH); 

    Path arrowIni = new Path(); 

    // move to start point of curve 
    MoveTo move = new MoveTo(curve1.getStartX(), curve1.getStartY()); 

    // transform tangent by rotating with +angle 
    Point2D p = rotation.transform(tan); 

    LineTo a1 = new LineTo(p.getX(), p.getY()); 
    // position relative to end point 
    a1.setAbsolute(false); 

    // same as above, but in oposite direction 
    rotation.setAngle(-ARROW_ANGLE); 
    p = rotation.transform(tan); 
    LineTo a2 = new LineTo(p.getX(), p.getY()); 
    a2.setAbsolute(false); 

    arrowIni.getElements().addAll(move, a1, move, a2); 

    // direction = inwards from the end point 
    tan = new Point2D(
      curve1.getControlX2() - curve1.getEndX(), 
      curve1.getControlY2() - curve1.getEndY() 
    ).normalize().multiply(ARROW_LENGTH); 
    move = new MoveTo(curve1.getEndX(), curve1.getEndY()); 
    p = rotation.transform(tan); 
    a1 = new LineTo(p.getX(), p.getY()); 
    a1.setAbsolute(false); 
    rotation.setAngle(ARROW_ANGLE); 
    p = rotation.transform(tan); 
    a2 = new LineTo(p.getX(), p.getY()); 
    a2.setAbsolute(false); 

    Path arrowEnd = new Path(); 
    arrowEnd.getElements().addAll(move, a1, move, a2); 

    root.getChildren().addAll(srcRect1, dstRect1, curve1, arrowIni, arrowEnd); 

    primaryStage.setScene(new Scene(root, 800, 600)); 
    primaryStage.show(); 
} 
+0

這就是我需要的! 謝謝! – unccoder