2

曲線が 90 度の角度で形状と交わるように、2 つの形状 (この質問では長方形) の間にベジェ曲線を生成したいと思います。MS ペイントで生成された例を次に示します。

曲線の例

私の目的のために、角度は任意のものではなく、軸に対して垂直である必要があるだけであると想定できます。つまり、端点での曲線の角度は、0、90、180、または 270 度である必要があるだけです。

ベジエ曲線を理解していると、2 つの端点と 2 つの制御点が必要であることがわかります。端点の計算は簡単ですが、制御点の操作方法については基本的な理解しかありません。

これを達成するための便利な公式はありますか?関連するチュートリアルを見つけるのに驚くほど苦労しています。

私は Java を使用しており、現在 java.awt.geom.Path2D.Double.curveTo() を使用して曲線を描いています。これを実現するための事前構築済みの Java クラスまたはメソッドがあれば理想的ですが、必要に応じてアルゴリズムや式を自分で実装したいと考えています。

4

2 に答える 2

2

Sage の優れた回答に基づいて、しばらくの間http://www.openprocessing.org/sketch/2123をいじった後、これが私が最終的に得たものです。

作成したい角度と同一線上に制御点を置くと、曲線がその方向に引っ張られます。コントロール ポイントがエンドポイントから離れているほど、効果が顕著になります。私は 90 度の角度しか扱っていないので、コントロール ポイントの x または y 座標を一定の距離 (Sage のようにデルタと呼んでいます) だけ変更して、目的の効果を生み出すことができます。デルタを見つけるために派手なものは何も使用しませんでした。満足のいく値が見つかるまで、いくつかの値を試しただけです。

これが私の最終的なコードのスニペットです。

public class BezierCurve {
    private CubicCurve2D curve;

    private static final int delta = 100;

    private double x1, y1, x2, y2;
    private double ctrlx1, ctrly1, ctrlx2, ctrly2;

    public BezierCurve(Point p1, Side side1, Point p2, Side side2) {
        this.x1 = p1.x;
        this.y1 = p1.y;
        this.x2 = p2.x;
        this.y2 = p2.y;

        Point ctrl1 = getControlPoint(p1, side1);
        Point ctrl2 = getControlPoint(p2, side2);

        ctrlx1 = ctrl1.x;
        ctrly1 = ctrl1.y;
        ctrlx2 = ctrl2.x;
        ctrly2 = ctrl2.y;

        curve = new CubicCurve2D.Double();
        curve.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
    }

    private Point getControlPoint(Point p, Side s) {
        int x = p.x;
        int y = p.y;

        switch (s) {
        case Left:
            x -= delta;
            break;
        case Right:
            x += delta;
            break;
        case Bottom:
            y += delta;
            break;
        case Top:
            y -= delta;
            break;
        }
        return new Point(x, y);
    }

    public void draw(Graphics2D g2) {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.draw(curve);
    }
}

これにより、上、下、右、左の各ケースが処理されます。

実際のコードのスクリーンショットを次に示します。

ここに画像の説明を入力

于 2013-11-14T03:27:18.267 に答える
1

のインテリジェントな使用により、目的をClass CubicCurve2D達成できるはずです。CubicCurve2D クラスはShapeインターフェイスを実装します。(x, y)このクラスは、座標空間の 3 次パラメトリック カーブ セグメントを表します。サブクラスは 3 次曲線と精度を指定CubicCurve2D.Floatします。CubicCurve2D.Doublefloatdouble

このクラスでsetCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2); は、2 つの制御点を設定できます。(ctrlx1, ctrly1)曲線開始の直前と曲線終了の直後に制御点を設定するとし(ctrlx2, ctrly2)ます。曲線の角度を度の倍数に維持するために90、次のように同様に制御点を計算できます (これは に対して計算されます90 deegree)。

ctrlx1 = x1; // curve start x
ctrly1 = y2 - delta; // curve start y
ctrlx2 = x1 + delta; // curve end x
ctrly2 = y2; // curve end y

次の例では、私は仮定していdelta = 10ます。

ここに画像の説明を入力

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g); 

    Graphics2D g2d = (Graphics2D) g.create();
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    CubicCurve2D c = new CubicCurve2D.Double();
    int x1 = 150, y1 = 150;  //p1
    int x2 = 350, y2 = 300;//p3
    int ctrlx1, ctrly1, ctrlx2, ctrly2;
    int delta = 10;

    ctrlx1 = x1; // curve start x
    ctrly1 = y2 - delta; // curve start y
    ctrlx2 = x1 + delta; // curve end x
    ctrly2 = y2; 

    g2d.drawRect(x1-50, y1-100, 100, 100);
    c.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
    g2d.drawRect(x2, y2-50, 100, 100);
    g2d.draw(c);
}
于 2013-11-06T17:29:30.267 に答える