【问题标题】:javafx CubicCurve arrow with angle and length带有角度和长度的 javafx CubicCurve 箭头
【发布时间】:2016-08-08 16:16:42
【问题描述】:

对于简单的行,我编写了以下代码:

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;
}

【问题讨论】:

  • 你想做什么?在三次曲线的末端画一个箭头?

标签: java javafx


【解决方案1】:

请注意,这里不需要 evalevalDt 方法。除了起点和点之外,您不会在任何地方进行评估,在这种情况下,起点和终点是 eval 方法的结果,evalDt 方法的结果分别是 control1 - startcontrol2 - end

也可以使用tan.angle(1, 0) 计算直线角度(即通过确定切线向量和 x 轴之间的角度)。

此外,可以使用 relative PathElements,即使用相对于最后一个 PathElement 的终点的位置。这稍微简化了箭头。

在以下示例中,除了相对 LineTos 之外,还使用 ​​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();
}

【讨论】:

  • 这就是我需要的!谢谢!
猜你喜欢
  • 2021-05-14
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 2019-02-24
相关资源
最近更新 更多