三次曲线JavaFX [英] CubicCurve JavaFX

查看:34
本文介绍了三次曲线JavaFX的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 JavaFX 中使用 CubicCurve 时遇到了困难.例如,如何绘制: y=x^3 ?绘制曲线的机制看起来很笨拙.

I am having a hard time with the CubicCurve in JavaFX. How can one draw for example: y=x^3 ? the mechanism to draw the curve look very unwieldy.

是否也可以将曲线的一个端点连接到另一个节点,那么当该节点的位置发生变化时,曲线会适应它?

Also is it possible to connect one of the endpoints of the curve to another Node, so when the location of that Node changes the curve adapts to it?

谢谢.

推荐答案

我认为 JavaFX 中的 CubicCurves 并不像您想象的那样有效.JavaFX CubicCurve 是贝塞尔曲线,它与三次多项式完全不同,例如y=x^3 你通常在高中数学中遇到.关于贝塞尔曲线,您想知道的一切都在这里.

I think CubicCurves in JavaFX don't quite work as you think they might. A JavaFX CubicCurve is a Bezier curve which is quite different from the cubic polynomials such y=x^3 you normally encounter in high school mathematics. Everything you never wanted to know about Bezier curves is here.

贝塞尔曲线通常用于生成计算机图形中的平滑曲线.它们由起点和终点以及一组用于操纵曲线的控制点定义.您可以通过玩一个交互式示例来最好地了解它是如何工作的,您可以在其中拖动起点、终点和控制点以形成不同的曲线.

Bezier curves are often used for generating smooth curves in computer graphics. They are defined by start and end points and a set of control points for manipulating the curve. You can best see how it works by playing with an interactive example where you drag around the start, end and control points to form different curves.

一个怎么画例如:y=x^3?

How can one draw for example: y=x^3 ?

虽然可以求解贝塞尔方程以简化为多项式,例如 y=x^3,但您可能想在 math.stackexchange.com 数学家的素质将远高于例如我.

While it may be possible to solve the Bezier equations to reduce to a polynomial such as y=x^3, you might want to ask that question on math.stackexchange.com where the caliber of mathematicians is going to be much higher than, for instance, me.

实现此目的的另一种方法是运行一个循环,通过将函数应用于 x 值来计算 x 值的小增量的 y 值,然后为路径中的每个计算点添加一个 LineTo.以下问答演示了这种方法:

Another way to accomplish this is to run a loop, calculating the y value for small increments of x value by applying the function to the x value, then add a LineTo for each of the calculated points in a Path. The following question and answer demonstrates this approach:

是否可以将曲线的一个端点连接到另一个节点,那么当该节点的位置发生变化时,曲线会适应它?

is it possible to connect one of the endpoints of the curve to another Node, so when the location of that Node changes the curve adapts to it?

是的,试试下面的示例应用程序,其中曲线端点和控制点绑定到可拖动节点.曲线适应锚节点被拖拽时位置的变化.

Yes, try the sample application below where the curve end and control points are bound to draggable nodes. The curve adapts to the changes in the location of the anchor nodes as they are dragged around.

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;

/** Example of how a cubic curve works, drag the anchors around to change the curve. */
public class CubicCurveManipulator extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  @Override public void start(final Stage stage) throws Exception {
    CubicCurve curve = createStartingCurve();

    Line controlLine1 = new BoundLine(curve.controlX1Property(), curve.controlY1Property(), curve.startXProperty(), curve.startYProperty());
    Line controlLine2 = new BoundLine(curve.controlX2Property(), curve.controlY2Property(), curve.endXProperty(),   curve.endYProperty());

    Anchor start    = new Anchor(Color.PALEGREEN, curve.startXProperty(),    curve.startYProperty());
    Anchor control1 = new Anchor(Color.GOLD,      curve.controlX1Property(), curve.controlY1Property());
    Anchor control2 = new Anchor(Color.GOLDENROD, curve.controlX2Property(), curve.controlY2Property());
    Anchor end      = new Anchor(Color.TOMATO,    curve.endXProperty(),      curve.endYProperty());

    stage.setTitle("Cubic Curve Manipulation Sample");
    stage.setScene(new Scene(new Group(controlLine1, controlLine2, curve, start, control1, control2, end), 400, 400, Color.ALICEBLUE));
    stage.show();
  }

  private CubicCurve createStartingCurve() {
    CubicCurve curve = new CubicCurve();
    curve.setStartX(100);
    curve.setStartY(100);
    curve.setControlX1(150);
    curve.setControlY1(50);
    curve.setControlX2(250);
    curve.setControlY2(150);
    curve.setEndX(300);
    curve.setEndY(100);
    curve.setStroke(Color.FORESTGREEN);
    curve.setStrokeWidth(4);
    curve.setStrokeLineCap(StrokeLineCap.ROUND);
    curve.setFill(Color.CORNSILK.deriveColor(0, 1.2, 1, 0.6));
    return curve;
  }

  class BoundLine extends Line {
    BoundLine(DoubleProperty startX, DoubleProperty startY, DoubleProperty endX, DoubleProperty endY) {
      startXProperty().bind(startX);
      startYProperty().bind(startY);
      endXProperty().bind(endX);
      endYProperty().bind(endY);
      setStrokeWidth(2);
      setStroke(Color.GRAY.deriveColor(0, 1, 1, 0.5));
      setStrokeLineCap(StrokeLineCap.BUTT);
      getStrokeDashArray().setAll(10.0, 5.0);
    }
  }

  // a draggable anchor displayed around a point.
  class Anchor extends Circle { 
    Anchor(Color color, DoubleProperty x, DoubleProperty y) {
      super(x.get(), y.get(), 10);
      setFill(color.deriveColor(1, 1, 1, 0.5));
      setStroke(color);
      setStrokeWidth(2);
      setStrokeType(StrokeType.OUTSIDE);

      x.bind(centerXProperty());
      y.bind(centerYProperty());
      enableDrag();
    }

    // make a node movable by dragging it around with the mouse.
    private void enableDrag() {
      final Delta dragDelta = new Delta();
      setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          // record a delta distance for the drag and drop operation.
          dragDelta.x = getCenterX() - mouseEvent.getX();
          dragDelta.y = getCenterY() - mouseEvent.getY();
          getScene().setCursor(Cursor.MOVE);
        }
      });
      setOnMouseReleased(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          getScene().setCursor(Cursor.HAND);
        }
      });
      setOnMouseDragged(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          double newX = mouseEvent.getX() + dragDelta.x;
          if (newX > 0 && newX < getScene().getWidth()) {
            setCenterX(newX);
          }  
          double newY = mouseEvent.getY() + dragDelta.y;
          if (newY > 0 && newY < getScene().getHeight()) {
            setCenterY(newY);
          }  
        }
      });
      setOnMouseEntered(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          if (!mouseEvent.isPrimaryButtonDown()) {
            getScene().setCursor(Cursor.HAND);
          }
        }
      });
      setOnMouseExited(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          if (!mouseEvent.isPrimaryButtonDown()) {
            getScene().setCursor(Cursor.DEFAULT);
          }
        }
      });
    }

    // records relative x and y co-ordinates.
    private class Delta { double x, y; }
  }  
}

示例程序输出:

这篇关于三次曲线JavaFX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆