' Return F(X, Y).
Private Function F(ByVal X As Single, ByVal Y As Single) As _
Single
F = X * X * X * X - 2 * X * X + Y * Y
End Function
' Return the partial derivative of dF/dX.
Private Function dFdX(ByVal X As Single, ByVal Y As Single) _
As Single
dFdX = 4 * X * X * X - 4 * X
End Function
' Return the partial derivative of dF/dY.
Private Function dFdY(ByVal X As Single, ByVal Y As Single) _
As Single
dFdY = 2 * Y
End Function
' Find a point on the curve close to this one.
Private Sub FindPointOnCurve(ByRef X As Single, ByRef Y As _
Single, ByVal level As Single, Optional ByVal start_x _
As Single = 0.1, Optional ByVal start_y As Single = _
0.2, Optional ByVal tolerance As Single = 0.01, _
Optional ByVal initial_delta As Single = 0.1)
Dim dZ As Single
Dim dist As Single
Dim delta As Single
Dim F_XY As Single
Dim dx As Single
Dim dy As Single
Dim direction As Integer
' Start at the starting point.
X = start_x
Y = start_y
delta = initial_delta
' Repeat until we have a decent solution.
Do
' See how far off we are.
F_XY = F(X, Y)
dZ = level - F_XY
If Abs(dZ) < tolerance Then Exit Do
' See if we are switching directions.
If Sgn(dZ) <> direction Then
' We are switching directions. Decrease delta.
delta = delta / 2
direction = Sgn(dZ)
End If
' Get the gradient.
Gradient X, Y, dx, dy
If Abs(dx) + Abs(dy) < 0.001 Then Exit Do
' Move in the right direction.
X = X + dx * delta * direction
Y = Y + dy * delta * direction
'Debug.Print X; Y
Loop
End Sub
' Return the gradient at this point.
Private Sub Gradient(ByVal X As Single, ByVal Y As Single, _
ByRef dx As Single, ByRef dy As Single)
Dim dist As Single
dx = dFdX(X, Y)
dy = dFdY(X, Y)
dist = Sqr(dx * dx + dy * dy)
If Abs(dist) < 0.0001 Then
dx = 0
dy = 0
Else
dx = dx / dist
dy = dy / dist
End If
End Sub
' Plot the level curve F(X, Y) = level.
Private Sub PlotLevelCurve(ByVal pic As PictureBox, ByVal _
level As Single, ByVal xmin As Single, ByVal xmax As _
Single, ByVal ymin As Single, ByVal ymax As Single, _
Optional step_size As Single = 0.1, Optional ByVal _
start_x As Single = 1#, Optional ByVal start_y As _
Single = 1#, Optional ByVal tolerance As Single = 0.02)
#Const SHOW_TICS = False
Dim num_points As Integer
Dim X0 As Single
Dim Y0 As Single
Dim X As Single
Dim Y As Single
Dim dx As Single
Dim dy As Single
' Find a point (X0, Y0) on the level curve.
FindPointOnCurve X0, Y0, level, start_x, start_y, _
tolerance
' Start here.
pic.CurrentX = X0
pic.CurrentY = Y0
num_points = 1
' Start following the level curve.
X = X0
Y = Y0
Do
' Find the next point along the curve.
Gradient X, Y, dx, dy
If Abs(dx) + Abs(dy) < 0.001 Then Exit Do
X = X + dy * step_size
Y = Y - dx * step_size
FindPointOnCurve X, Y, level, X, Y, tolerance
' Draw to this point.
pic.Line -(X, Y)
#If SHOW_TICS Then
pic.Line -Step(dx * 0.1, dy * 0.1)
pic.Line -Step(-dx * 0.1, -dy * 0.1)
#End If
num_points = num_points + 1
' See if the point is outside the drawing area.
If X < xmin Or X > xmax Or _
Y < ymin Or Y > ymax _
Then Exit Do
' If we have gone at least 4 points, see if this
' is where we started.
If num_points >= 4 Then
If Sqr((X0 - X) * (X0 - X) + (Y0 - Y) * (Y0 - _
Y)) <= step_size * 1.1 Then
pic.Line -(X0, Y0)
Exit Do
End If
End If
Loop
End Sub
|