tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルSpline Chart で補完部分の値を得たい
記事No11993
投稿日: 2019/07/19(Fri) 12:12
投稿者食器
Visual Basic の SplineChart について

知りたいことは次の2点いずれかです。
@SplineChartの任意のxに対するyの値の取得
AVBのSplineと同じ曲線を描くための数学関数を求める方法

今年の4月からプログラミングを勉強中で
現在はVisual Studio 2017 で、VBでのコードを書いてます。
こちらのサイトを大いに参考にさせて頂いております。


お尋ねしたいのですが、
ChartTypeをSplineに設定して3点を追加すると、
グラフ上にその3点を通る曲線が描かれると思います。

このとき指定したxの値に対する
曲線上のyの値を取得することは可能でしょうか?

取得方法があれば教えて頂きたいです。




自分では方法がわからなかったので、
今はスプライン補間を計算により行うことで数値を取得しています。

http://morimori2008.web.fc2.com/contents/PCprograming/VB/VB.html
こちらのプログラムを参考にして行列計算を行い、
三次関数の係数を求め、方程式を得ることでPointChartとして描いています。

例えば3点が(1,1),(4,7),(5,3)の場合は以下のようになります。

Dim a As New personal_muth.matrix2D(8, 8)
Dim a_inverse(7, 7) As Double

a.matrix(0, 0) = 1 : a.matrix(0, 1) = 1 : a.matrix(0, 2) = 1 : a.matrix(0, 3) = 1 : a.matrix(0, 4) = 0 : a.matrix(0, 5) = 0 : a.matrix(0, 6) = 0 : a.matrix(0, 7) = 0
a.matrix(1, 0) = 64 : a.matrix(1, 1) = 16 : a.matrix(1, 2) = 4 : a.matrix(1, 3) = 1 : a.matrix(1, 4) = 0 : a.matrix(1, 5) = 0 : a.matrix(1, 6) = 0 : a.matrix(1, 7) = 0
a.matrix(2, 0) = 0 : a.matrix(2, 1) = 0 : a.matrix(2, 2) = 0 : a.matrix(2, 3) = 0 : a.matrix(2, 4) = 64 : a.matrix(2, 5) = 16 : a.matrix(2, 6) = 4 : a.matrix(2, 7) = 1
a.matrix(3, 0) = 0 : a.matrix(3, 1) = 0 : a.matrix(3, 2) = 0 : a.matrix(3, 3) = 0 : a.matrix(3, 4) = 125 : a.matrix(3, 5) = 25 : a.matrix(3, 6) = 5 : a.matrix(3, 7) = 1
a.matrix(4, 0) = 48 : a.matrix(4, 1) = 8 : a.matrix(4, 2) = 1 : a.matrix(4, 3) = 0 : a.matrix(4, 4) = -48 : a.matrix(4, 5) = -8 : a.matrix(4, 6) = -1 : a.matrix(4, 7) = 0
a.matrix(5, 0) = 24 : a.matrix(5, 1) = 2 : a.matrix(5, 2) = 0 : a.matrix(5, 3) = 0 : a.matrix(5, 4) = -24 : a.matrix(5, 5) = -2 : a.matrix(5, 6) = 0 : a.matrix(5, 7) = 0
a.matrix(6, 0) = 6 : a.matrix(6, 1) = 2 : a.matrix(6, 2) = 0 : a.matrix(6, 3) = 0 : a.matrix(6, 4) = 0 : a.matrix(6, 5) = 0 : a.matrix(6, 6) = 0 : a.matrix(6, 7) = 0
a.matrix(7, 0) = 0 : a.matrix(7, 1) = 0 : a.matrix(7, 2) = 0 : a.matrix(7, 3) = 0 : a.matrix(7, 4) = 30 : a.matrix(7, 5) = 2 : a.matrix(7, 6) = 0 : a.matrix(7, 7) = 0

a_inverse = a.inverse()

Dim b(7) As Double
b(0) = 1 : b(1) = 7 : b(2) = 7 : b(3) = 3 : b(4) = 0 : b(5) = 0 : b(6) = 0 : b(7) = 0
Dim ans(7) As Double
Dim i, j As Integer

For i = 0 To 7
 For j = 0 To 7
  ans(i) = ans(i) + a_inverse(i, j) * b(j)
 Next
Next

Chart1.Series.Add("DotSpline") 'オレンジ色の計算して描いたSpline
With Chart1.Series("DotSpline")
 .ChartType = DataVisualization.Charting.SeriesChartType.Point
 .MarkerStyle = DataVisualization.Charting.MarkerStyle.Circle
 .MarkerSize = 3
 .MarkerColor = Color.Orange
 .MarkerStep = 1
End With

Dim x, y As Double
x = 0

Do
 If 1 <= x And x <= 4 Then
  y = ans(0) * x ^ 3 + ans(1) * x ^ 2 + ans(2) * x + ans(3)
  Chart1.Series("DotSpline").Points.AddXY(x, y)
 ElseIf 4 < x And x <= 5 Then
  y = ans(4) * x ^ 3 + ans(5) * x ^ 2 + ans(6) * x + ans(7)
  Chart1.Series("DotSpline").Points.AddXY(x, y)
 End If

 x = x + 0.01

Loop Until x > 5


Chart1.Series.Add("Spline") '青色のVBSplineChart

With Chart1.Series("Spline")
 .ChartType = DataVisualization.Charting.SeriesChartType.Spline
End With

Chart1.Series("Spline").Points.AddXY(1, 1)
Chart1.Series("Spline").Points.AddXY(4, 7)
Chart1.Series("Spline").Points.AddXY(5, 3)


結果を見ると確かに3点を通るのですが、
計算して描いたオレンジと元々の青色が一致しません。

自然スプラインを描くように端点の2次導関数を0とする境界条件が誤っているのでしょうか?
それとも、そもそも3次関数ではないのでしょうか
調べたところVBのSplineにテンション設定値があるとも見受けられましたが、それが関係するのでしょうか?


@SplineChartの任意のxに対するyの値の取得
AVBのSplineと同じ曲線を描くための数学関数を求める方法

このいずれかを知りたく思います。

[ツリー表示へ]
タイトルRe: Spline Chart で補完部分の値を得たい【自己解決】
記事No11995
投稿日: 2019/08/16(Fri) 09:52
投稿者食器

hhttps://t-pot.com/program/2_3rdcurve/index.html

こちらのサイトを参考にして
Catmull-Romスプライン曲線を描写したところ、
VBでのSplineChartと一致しました。(目視の範囲でですが)

ただし端の扱いは上記のサイトと異なっていました。


        'Chartのsetは省略

        '宣言
        Dim t As Double = 0
        Dim x, y As Double
        Dim x0, x1, x2, x3 As Double
        Dim y0, y1, y2, y3 As Double

    '任意の4点の場合
        x0 = 2 : y0 = 6
        x1 = 7 : y1 = 11
        x2 = 11 : y2 = 7
        x3 = 15 : y3 = 13

        '中
        Do
            x = (-0.5 * x0 + 1.5 * x1 - 1.5 * x2 + 0.5 * x3) * (t ^ 3) + (x0 - 2.5 * x1 + 2 * x2 - 0.5 * x3) * (t ^ 2) + (-0.5 * x0 + 0.5 * x2) * t + x1
            y = (-0.5 * y0 + 1.5 * y1 - 1.5 * y2 + 0.5 * y3) * (t ^ 3) + (y0 - 2.5 * y1 + 2 * y2 - 0.5 * y3) * (t ^ 2) + (-0.5 * y0 + 0.5 * y2) * t + y1
            Chart1.Series("DotSpline").Points.AddXY(x, y)
            t = t + 0.01
        Loop Until t > 1

        t = 0

        '始端
        Do
            x = (-0.5 * x0 + 1.5 * x0 - 1.5 * x1 + 0.5 * x2) * (t ^ 3) + (x0 - 2.5 * x0 + 2 * x1 - 0.5 * x2) * (t ^ 2) + (-0.5 * x0 + 0.5 * x1) * t + x0
            y = (-0.5 * y0 + 1.5 * y0 - 1.5 * y1 + 0.5 * y2) * (t ^ 3) + (y0 - 2.5 * y0 + 2 * y1 - 0.5 * y2) * (t ^ 2) + (-0.5 * y0 + 0.5 * y1) * t + y0
            Chart1.Series("DotSpline").Points.AddXY(x, y)
            t = t + 0.01
        Loop Until t > 1

        t = 0

        '終端
        Do
            x = (-0.5 * x1 + 1.5 * x2 - 1.5 * x3 + 0.5 * x3) * (t ^ 3) + (x1 - 2.5 * x2 + 2 * x3 - 0.5 * x3) * (t ^ 2) + (-0.5 * x1 + 0.5 * x3) * t + x2
            y = (-0.5 * y1 + 1.5 * y2 - 1.5 * y3 + 0.5 * y3) * (t ^ 3) + (y1 - 2.5 * y2 + 2 * y3 - 0.5 * y3) * (t ^ 2) + (-0.5 * y1 + 0.5 * y3) * t + y2
            Chart1.Series("DotSpline").Points.AddXY(x, y)
            t = t + 0.01
        Loop Until t > 1



要するに端の扱いは、
係数は中の部分と同じで、点がない部分はその近くの点の値を使用する
というものでした。

[ツリー表示へ]
タイトルRe: Spline Chart で補完部分の値を得たい【自己解決】
記事No11996
投稿日: 2019/08/16(Fri) 09:53
投稿者食器

hhttps://t-pot.com/program/2_3rdcurve/index.html

こちらのサイトを参考にして
Catmull-Romスプライン曲線を描写したところ、
VBでのSplineChartと一致しました。(目視の範囲でですが)

ただし端の扱いは上記のサイトと異なっていました。


        'Chartのsetは省略

        '宣言
        Dim t As Double = 0
        Dim x, y As Double
        Dim x0, x1, x2, x3 As Double
        Dim y0, y1, y2, y3 As Double

    '任意の4点の場合
        x0 = 2 : y0 = 6
        x1 = 7 : y1 = 11
        x2 = 11 : y2 = 7
        x3 = 15 : y3 = 13

        '中
        Do
            x = (-0.5 * x0 + 1.5 * x1 - 1.5 * x2 + 0.5 * x3) * (t ^ 3) + (x0 - 2.5 * x1 + 2 * x2 - 0.5 * x3) * (t ^ 2) + (-0.5 * x0 + 0.5 * x2) * t + x1
            y = (-0.5 * y0 + 1.5 * y1 - 1.5 * y2 + 0.5 * y3) * (t ^ 3) + (y0 - 2.5 * y1 + 2 * y2 - 0.5 * y3) * (t ^ 2) + (-0.5 * y0 + 0.5 * y2) * t + y1
            Chart1.Series("DotSpline").Points.AddXY(x, y)
            t = t + 0.01
        Loop Until t > 1

        t = 0

        '始端
        Do
            x = (-0.5 * x0 + 1.5 * x0 - 1.5 * x1 + 0.5 * x2) * (t ^ 3) + (x0 - 2.5 * x0 + 2 * x1 - 0.5 * x2) * (t ^ 2) + (-0.5 * x0 + 0.5 * x1) * t + x0
            y = (-0.5 * y0 + 1.5 * y0 - 1.5 * y1 + 0.5 * y2) * (t ^ 3) + (y0 - 2.5 * y0 + 2 * y1 - 0.5 * y2) * (t ^ 2) + (-0.5 * y0 + 0.5 * y1) * t + y0
            Chart1.Series("DotSpline").Points.AddXY(x, y)
            t = t + 0.01
        Loop Until t > 1

        t = 0

        '終端
        Do
            x = (-0.5 * x1 + 1.5 * x2 - 1.5 * x3 + 0.5 * x3) * (t ^ 3) + (x1 - 2.5 * x2 + 2 * x3 - 0.5 * x3) * (t ^ 2) + (-0.5 * x1 + 0.5 * x3) * t + x2
            y = (-0.5 * y1 + 1.5 * y2 - 1.5 * y3 + 0.5 * y3) * (t ^ 3) + (y1 - 2.5 * y2 + 2 * y3 - 0.5 * y3) * (t ^ 2) + (-0.5 * y1 + 0.5 * y3) * t + y2
            Chart1.Series("DotSpline").Points.AddXY(x, y)
            t = t + 0.01
        Loop Until t > 1



要するに端の扱いは、
係数は中の部分と同じで、点がない部分はその近くの点の値を使用する
というものでした。

[ツリー表示へ]