8

JavaFX の CubicCurve で苦労しています。たとえば、どのように描画できますか: y=x^3 ? 曲線を描くメカニズムは非常に扱いにくいように見えます。

また、曲線の終点の 1 つを別のノードに接続して、そのノードの位置が変更されたときに曲線がそれに適応するようにすることは可能ですか?

ありがとう。

4

1 に答える 1

22

JavaFX の CubicCurves は、あなたが思っているようには機能しないと思います。JavaFX CubicCurve は、高校の数学で通常遭遇する y=x^3 などの 3 次多項式とはまったく異なるベジエ曲線です。ベジエ曲線について知りたくないことはすべてここにあります。

ベジエ曲線は、コンピュータ グラフィックスで滑らかな曲線を生成するためによく使用されます。これらは、始点と終点、および曲線を操作するための一連の制御点によって定義されます。開始点、終了点、および制御点の周りをドラッグしてさまざまな曲線を形成するインタラクティブな例を試してみると、どのように機能するかを最もよく理解できます。

たとえば、どのように描画できますか: y=x^3 ?

ベジエ方程式を解いて y=x^3 などの多項式に還元することは可能かもしれませんが、数学者の能力がはるかに高くなるmath.stackexchange.comでその質問をしたいかもしれません。たとえば、私。

これを達成する別の方法は、ループを実行し、関数を x 値に適用して x 値の小さな増分の y 値を計算し、Path 内の計算されたポイントごとに LineTo を追加することです。次の質問と回答は、このアプローチを示しています。

曲線の終点の 1 つを別のノードに接続して、そのノードの位置が変更されたときに曲線がそれに適応することは可能ですか?

はい、曲線の終点と制御点がドラッグ可能なノードにバインドされている以下のサンプル アプリケーションを試してください。曲線は、アンカー ノードがドラッグされると、アンカー ノードの位置の変化に適応します。

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

サンプル プログラム出力:

cubecurve サンプル プログラムの出力

于 2012-10-24T23:07:02.350 に答える