8

2点間にベジエ曲線があります。すべての曲線を 2 つの等しい半分にカットしたいと思います。私の考えの 1 つは、「t」値を制御できる場合、t = [0,0.5] と t = [0.5,1] で 2 つの曲線を描くことですが、方法がわかりません。以下は私のコードです。他のアイデアや提案は気にしません

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>D3 test</title>
    <script src="http://d3js.org/d3.v3.min.js"></script>

    <script>
    var Over = function(){
        d3.select(this)
        .style("stroke-opacity", 0.25);
    }
    var Out = function(){
        d3.select(this)
        .transition().duration(200)
        .style("stroke-opacity", 0);
    }

    function curve(n,x1,y1,x2,y2){

        var xr = (x1+x2)/2,
            yr = (y1+y2)/2,
            euDist = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)),
            x3 = -y1+xr+yr, x4 = -y2+xr+yr,
            y3 =  x1+yr-xr, y4 =  x2+yr-xr,
            ctrl , curveDescription;

        svg.append('path')
            .attr("stroke", 'blue')
            .attr('fill','none')
            .style("stroke-opacity",0.25)
            .attr('d', 'M'+x3+','+y3+'L'+x4+','+y4)
            .attr('stroke-width',strokeWidth);

        for(var j=0;j<=n;j++){
            ctrl = [(x4-x3)*j/n+x3 , (y4-y3)*j/n+y3] ,                  
            curveDescription=   
                    'M' +x1+','     +y1+ 
                    'Q' +ctrl[0]+','+ctrl[1]+','
                        +x2+','     +y2;

            svg.append('path')
                .attr("stroke", 'blue')
                .attr('fill','none')
                .style("stroke-opacity",0.25)
                .attr('d', curveDescription)
                .attr('stroke-width',strokeWidth);  

            svg.append('path')
                .attr("stroke", 'blue')
                .attr('fill','none')
                .style("stroke-opacity",0)
                .on("mouseover", Over)
                .on("mouseout", Out)
                .attr('d', curveDescription)
                .attr('stroke-width',strokeWidth*25);

        }

    }
    </script>

</head>

<body>
    <script>
    var w = 1268 , h = 680 , strokeWidth = 2;

    var svg = d3.select("body")
                .append("svg")
                .attr("width", w)
                .attr("height", h)

    curve(5, 100,100, 400,500);


    </script>
</body>
</html>
4

3 に答える 3

26

ベジエを 2 つの曲線に分割するのは非常に簡単です。De Casteljau のアルゴリズムを参照してください。 https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm

アップデート

De Casteljauは見た目よりシンプルです。その WP 記事は、非数学者にとってより明確になる可能性があります。なので、もっと簡単に説明します。

ポイント A、B、C、D で定義されたベジエがあるとします。ここで、A と D はエンドポイント、B と C はコントロール ポイントです。

したがって、曲線に沿った点 't' で曲線の値を見つけたいとします (ここで、t は 0..1 の範囲にあります。ジオメトリによって次のように行うことができます。

  1. 直線 AB に沿って 't' にある点 E を見つけます。
  2. 直線 BC に沿って 't' にある点 F を見つけます。
  3. 直線 CD に沿って 't' にある点 G を見つけます。

  4. 直線 EF に沿って 't' にある点 H を見つけます。

  5. 直線 FG に沿って 't' にある点 J を見つけます。

  6. 最後に、直線 HJ に沿って 't' にある点 K を見つけます。

K は、ベジエに沿った 't' の点にも等しくなります。これが De Casteljau のアルゴリズムです。

しかし便利なことに、曲線が点 K で分割された場合に生じる 2 つのベジエの制御点も得られます。2 つのベジエ曲線は、A、E、H、K および K、J、G、D です。

あなたのケースでは t=0.5 であるため、2 つの曲線を見つけることは、加算と 2 による除算のシーケンスにすぎません。

  E = (A+B)/2
  F = (B+C)/2
  G = (C+D)/2
  H = (E+F)/2
  J = (F+G)/2
  K = (H+J)/2

明らかに、これらの計算はそれぞれ x と y に対して実行する必要があります。

お役に立てれば。

于 2013-09-08T07:05:17.920 に答える
14

Paul LeBeau によるこの質問への回答は、私にとって非常に役に立ちました。その答えに沿ったビジュアルがあれば、他の人はさらに恩恵を受けると思いました。それを以下に示します.

次の図は、Paul LeBeau の回答で説明されているポイントを示しています。関連する説明については、その回答を参照してください。実際の図は t=0.5 の特殊なケースを示していますが、一般原則は 0 から 1 の間の t の任意の値に対して同じです。太い黒い線は元の曲線の「制御線」を示し、赤い線は元の曲線の「制御線」を示しています。最初の「ハーフカーブ」。

ここに画像の説明を入力

于 2016-04-05T18:54:49.933 に答える