f stands for function in the generalized notation y=f(x). The function is an equation that for any x or for any x in a specific interval returns a value for y. In the same way a vba function is a formulation that returns a value to be captured in a variable.
We have a good loop template to process equations, but whenever a new equation is to be used, the entire sub procedure is copied to a new name and just one line of code with the equation is changed. The goal is to reduce the duplicated code. If we write the equation into a function to return a value, we still need unique sub procedures to call the correct function, but putting the equations into functions to return a value then calling the function in the loop seems like a road that will go somewhere.
We will make the function name look like the equation it contains for now, but this will be too cumbersome to maintain. We will make an index using a spreadsheet to keep track of function names and their equations.
for our two rose petal equations
R = B * Sin (C*A) + D
R = B * Cos (C*A) + D
Function B_Sin_C_A_D(A_rad As Double) As Double 'R = B * Sin(C * A) + D B_Sin_C_A_D = B * Sin(C * A_rad) + D End Function Function B_Cos_C_A_D(A_rad As Double) As Double 'R = B * Cos(C * A) + D B_Cos_C_A_D = B * Cos(C * A_rad) + D End Function
If we cannot call either of these functions from a single subprocedure, we have not reduced anything. We need a method to call a function by passing its name.
in the loop where we used to have
‘R = B * Sin(C * A_rad) + D
The only value on the right side of the equation that is changing each time through the loop is A_rad. To simplify things we make the other variables global so we do not have to pass them. A_rad is the radian conversion of A degrees, which is our changing interval variable since we are doing a polar equation. It corresponds to x in a rectangular equation.
we can now have
R = Application.Run(funcname, A_rad)
Sub petal(funcname As String) Call connect_acad Dim R As Double, A As Integer Dim X As Double, Y As Double Dim A_rad As Double Dim i As Integer, numpts As Integer Dim plineobj As AcadLWPolyline Dim pt() As Double numpts = (Amax - Amin) / A_inc 'num of lines numpts = numpts + 1 ReDim pt(1 To numpts * 2) For i = 1 To numpts A = Amin + ((i - 1) * A_inc) A_rad = deg2rad(A) R = Application.Run(funcname, A_rad) X = R * Cos(A_rad) Y = R * Sin(A_rad) pt(i * 2 - 1) = X: pt(i * 2) = Y Next i Set plineobj = acadDoc.ModelSpace.AddLightWeightPolyline(pt) Update End Sub
The upper level calling program can now look like a recipe. This will change when we integrate this into a form. The variables that go into an actual graph are all made globals – Amin, Amax, A_inc, B, C, D, and funcname.
Sub call_petal() 'R = B * Sin(C * A) + D funcname = "B_Sin_C_A_D" Amin = 0 Amax = 360 A_inc = 1 B = 3 C = 5 D = 2 Call petal(funcname) End Sub
This makes the whole structure more complicated, and detracts from the core graphing code, but something along this line seems necessary to reduce the multiplication of subprocedures which only differ by the function being graphed.