Skip to content

Commit dbf9a9d

Browse files
committed
Added Distance and LinesIntersect functions
1 parent 81c6651 commit dbf9a9d

File tree

1 file changed

+172
-21
lines changed

1 file changed

+172
-21
lines changed

src/VBAexpressions.cls

Lines changed: 172 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -316,22 +316,22 @@ Private Sub Class_Initialize()
316316
P_FORMATRESULT = False
317317
BuildinFunctIDList = "abs;floor;achisq;asin;acos;aerf;afishf;agauss;asc;anorm;atn;astudt;array;avg;beta.dist" & _
318318
";betainv;ceil;chisq;cholesky;cholinverse;cholsolve;chr;cos;choose;date;dateadd;datediff" & _
319-
";datepart;dateserial;datevalue;day;ddb;det;erf;exp;fishf;fit;format;fv;fzero" & _
320-
";gamma;gammaln;gauss;get;hour;ibeta;iff;instr;inverse;ipmt;irr;lcase;left;len;log;lgn" & _
319+
";datepart;dateserial;datevalue;day;ddb;det;distance;erf;exp;fishf;fit;format;fv;fzero" & _
320+
";gamma;gammaln;gauss;get;hour;ibeta;iff;instr;inverse;ipmt;irr;lcase;left;len;linesintersect;log;lgn" & _
321321
";ln;lsqrsolve;ludecomp;lusolve;max;mid;min;minute;mirr;mlr;mmult;mneg;mround" & _
322-
";msum;mtranspose;month;monthname;norm;now;nper;npv;percent;pmt;ppmt;pow;pv" & _
322+
";msum;mtranspose;month;monthname;norm;now;nper;npv;parallel;percent;perpendicular;pmt;ppmt;pow;pv" & _
323323
";qr;rate;rem;replace;right;round;sgn;sin;sln;solve;sqr;sqrt;sum;studt;switch" & _
324324
";syd;tan;timeserial;timevalue;tinv;tinv_1t;tinv_2t;trim;ucase;weekday" & _
325325
";weekdayname;year"
326326
BuildinFunctNameList = "Absolute;aFloor;ACHISQ;ArcSin;ArcCos;AERF;AFISHF;AGAUSS;ASCII;ANORM;ArcTan" & _
327327
";ASTUDT;strArray;Average;Beta_Distribution;BETAINV;aCeiling;CHISQ;CholeskyDec;CholeskyInverseMatrix" & _
328328
";CholeskySolve;ASCIIchr;Cosin;aChoose;aDate;aDateAdd;aDateDiff;aDatePart;aDateSerial" & _
329-
";aDateValue;aDay;aDDB;MatrixDeterminant;ERF;ExpEuler;FISHF;CurveFit" & _
329+
";aDateValue;aDay;aDDB;MatrixDeterminant;Distance;ERF;ExpEuler;FISHF;CurveFit" & _
330330
";aFormat;aFV;FunctionZero;Gamma;GammaLN;GAUSS;GET;aHour;iBETA;aIff;aInstr;InverseMatrix" & _
331-
";aIPMT;aIRR;LowerCase;aLeft;aLen;Logarithm;LgN;LN;LSQRsolve;LUdecomposition" & _
331+
";aIPMT;aIRR;LowerCase;aLeft;aLen;LinesIntersect;Logarithm;LgN;LN;LSQRsolve;LUdecomposition" & _
332332
";LUSolveLinearSystem;Max;Middle;Min;aMinute;aMIRR;MultiLinearReg;MatrixMult" & _
333333
";MatrixNegation;MatrixRound;MatrixSum;MatrixTranspose;aMonth;aMonthName;NORM" & _
334-
";aNow;aNPER;aNPV;Percent;aPMT;aPPMT;Power;aPV;QRdecomposition;aRATE;REM" & _
334+
";aNow;aNPER;aNPV;ParallelLine;Percent;PerpendicularLine;aPMT;aPPMT;Power;aPV;QRdecomposition;aRATE;REM" & _
335335
";aReplace;aRight;ROUND;Sign;Sine;aSLN;SolveLinearSystem;SquareRoot;SquareRoot;SUM" & _
336336
";STUDT;aSwitch;aSYD;Tangent;aTimeSerial;aTimeValue;TINV;TINV_1T;TINV_2T;aTrim" & _
337337
";aUcase;aWweekDay;aWeekDayName;aYear"
@@ -1632,7 +1632,7 @@ Private Function BETAINV_(p As Double, A As Double, B As Double) As Double
16321632
Dim a1, b1 As Double
16331633
Dim j As Long
16341634
Dim lna As Double, lnb As Double
1635-
Dim pp As Double, t As Double
1635+
Dim PP As Double, t As Double
16361636
Dim u As Double, err As Double
16371637
Dim x As Double, H As Double
16381638
Dim w As Double, afac As Double
@@ -1649,11 +1649,11 @@ Private Function BETAINV_(p As Double, A As Double, B As Double) As Double
16491649
End If
16501650
If A >= 1 And B >= 1 Then
16511651
If p < 0.5 Then
1652-
pp = p
1652+
PP = p
16531653
Else
1654-
pp = 1 - p
1654+
PP = 1 - p
16551655
End If
1656-
t = Sqr(-2 * Log(pp))
1656+
t = Sqr(-2 * Log(PP))
16571657
x = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t
16581658
If p < 0.5 Then x = -x
16591659
aL = (x * x - 3) / 6
@@ -2887,6 +2887,45 @@ err_Handler:
28872887
d_lParenthesis & err.Description & d_rParenthesis
28882888
End Function
28892889

2890+
''' <summary>
2891+
''' Returns the distance between two given points. The points
2892+
''' must be given each one in array format, ex.:
2893+
''' {{x1;y1}};{{x2;y2}}
2894+
''' </summary>
2895+
Private Function Distance(ByRef expression As String, ByRef fName As String) As String
2896+
Dim argsCount As Long
2897+
Dim tmpData() As String
2898+
Dim tmpEval As String
2899+
Dim LB As Long, UB As Long
2900+
2901+
On Error GoTo err_Handler
2902+
tmpData() = SplitArgs(expression)
2903+
LB = LBound(tmpData)
2904+
UB = UBound(tmpData)
2905+
argsCount = UB - LB + 1
2906+
Select Case argsCount
2907+
Case 2
2908+
Dim aArray() As Variant
2909+
ReDim aArray(0 To 1)
2910+
2911+
aArray(0) = ToDblArray(ArrayFromString(tmpData(LB)))
2912+
aArray(1) = ToDblArray(ArrayFromString(tmpData(UB)))
2913+
tmpEval = ( _
2914+
(aArray(1)(0) - aArray(0)(0)) ^ 2 + _
2915+
(aArray(1)(1) - aArray(0)(1)) ^ 2 _
2916+
) ^ 0.5
2917+
Case Else
2918+
tmpEval = e_ValueError
2919+
BuildErrMessage errMissingArgsOrTooManyArgs, d_lCurly & fName & d_rCurly
2920+
End Select
2921+
Distance = tmpEval: Erase tmpData
2922+
Exit Function
2923+
err_Handler:
2924+
Distance = e_ValueError
2925+
BuildErrMessage errEvalError, d_lCurly & fName & d_rCurly & " | Error#: " & err.Number & d_Space & _
2926+
d_lParenthesis & err.Description & d_rParenthesis
2927+
End Function
2928+
28902929
''' <summary>
28912930
''' Finds for constant sub-expressions
28922931
''' </summary>
@@ -3018,6 +3057,7 @@ Private Function EvalFunction(ByRef Argument As String, ByRef FunctionName As St
30183057
Case "aDateValue": EvalFunction = DateValue_(Argument, FunctionName)
30193058
Case "aDay": EvalFunction = Day_(Argument, FunctionName)
30203059
Case "aDDB": EvalFunction = DDB_(Argument, FunctionName)
3060+
Case "Distance": EvalFunction = Distance(Argument, FunctionName)
30213061
Case "MatrixDeterminant": EvalFunction = Determinant(Argument, FunctionName)
30223062
Case "ERF": EvalFunction = ERF(Argument, FunctionName)
30233063
Case "ExpEuler": EvalFunction = ExpEuler(Argument, FunctionName)
@@ -3041,6 +3081,7 @@ Private Function EvalFunction(ByRef Argument As String, ByRef FunctionName As St
30413081
Case "aLeft": EvalFunction = Left_(Argument, FunctionName)
30423082
Case "aLen": EvalFunction = Len_(Argument, FunctionName)
30433083
Case "LowerCase": EvalFunction = LCase_(Argument, FunctionName)
3084+
Case "LinesIntersect": EvalFunction = LinesIntersect(Argument, FunctionName)
30443085
Case "Logarithm": EvalFunction = Logarithm(Argument, FunctionName)
30453086
Case "LgN": EvalFunction = LgN(Argument, FunctionName)
30463087
Case "LUdecomposition": EvalFunction = LUdecomposition(Argument, FunctionName)
@@ -5121,7 +5162,7 @@ Private Function iBETAINV(p As Double, A As Double, B As Double) As Double
51215162
Dim a1, b1 As Double
51225163
Dim j As Long
51235164
Dim lna As Double, lnb As Double
5124-
Dim pp As Double, t As Double
5165+
Dim PP As Double, t As Double
51255166
Dim u As Double, err As Double
51265167
Dim x As Double, H As Double
51275168
Dim w As Double, afac As Double
@@ -5138,11 +5179,11 @@ Private Function iBETAINV(p As Double, A As Double, B As Double) As Double
51385179
End If
51395180
If A >= 1 And B >= 1 Then
51405181
If p < 0.5 Then
5141-
pp = p
5182+
PP = p
51425183
Else
5143-
pp = 1 - p
5184+
PP = 1 - p
51445185
End If
5145-
t = Sqr(-2 * Log(pp))
5186+
t = Sqr(-2 * Log(PP))
51465187
x = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t
51475188
If p < 0.5 Then x = -x
51485189
aL = (x * x - 3) / 6
@@ -5770,6 +5811,116 @@ err_Handler:
57705811
d_lParenthesis & err.Description & d_rParenthesis
57715812
End Function
57725813

5814+
''' <summary>
5815+
''' This function return the intersection of two lines given
5816+
''' two ordered pairs of points for each line. The PointsInLine1
5817+
''' and PointsInLine2 arguments must have the array form |[x] [y]|
5818+
''' with the same size (2 rows and 2 columns). The returned value
5819+
''' is an array |[x] [y]| if the lines meet and a #Null error value
5820+
''' for parallel lines.
5821+
''' </summary>
5822+
Private Function LinesIntersection(ByRef PointsInLine1 As Variant, _
5823+
PointsInLine2 As Variant, Optional k As Integer = 1) As Variant
5824+
Dim i As Double
5825+
Dim j As Double
5826+
Dim m As Double
5827+
Dim n As Double
5828+
Dim O As Double
5829+
Dim PP As Double
5830+
Dim HomogeneousPointsL1(0 To 1, 0 To 2) As Variant
5831+
Dim HomogeneousPointsL2(0 To 1, 0 To 2) As Variant
5832+
Dim HomogeneousEcuations(0 To 1, 0 To 2) As Variant
5833+
Dim EcuationsProduct(0 To 0, 0 To 2) As Variant
5834+
Dim Intersection(0 To 0, 0 To 1) As Variant
5835+
5836+
If k <= 0 Then k = 1 'Ensure positive scalar value
5837+
m = LBound(PointsInLine1, 1)
5838+
n = LBound(PointsInLine1, 2)
5839+
'Represent the points with homogeneous coordinates
5840+
i = 0
5841+
For O = m To m + 1
5842+
j = 0
5843+
For PP = n To n + 2
5844+
If PP < n + 2 Then
5845+
HomogeneousPointsL1(i, j) = PointsInLine1(O, PP)
5846+
HomogeneousPointsL2(i, j) = PointsInLine2(O, PP)
5847+
Else
5848+
HomogeneousPointsL1(i, j) = k
5849+
HomogeneousPointsL2(i, j) = k
5850+
End If
5851+
j = j + 1
5852+
Next PP
5853+
i = i + 1
5854+
Next O
5855+
'Compute the lines homogeneous ecuations using Vectorial Matrix Products
5856+
HomogeneousEcuations(0, 0) = (HomogeneousPointsL1(0, 1) * HomogeneousPointsL1(1, 2)) - _
5857+
(HomogeneousPointsL1(1, 1) * HomogeneousPointsL1(0, 2)) '[a01*a12 - a11*a02]
5858+
HomogeneousEcuations(0, 1) = -1 * ((HomogeneousPointsL1(0, 0) * HomogeneousPointsL1(1, 2)) - _
5859+
(HomogeneousPointsL1(1, 0) * HomogeneousPointsL1(0, 2))) '-[a00*a12 - a10*a02]
5860+
HomogeneousEcuations(0, 2) = (HomogeneousPointsL1(0, 0) * HomogeneousPointsL1(1, 1)) - _
5861+
(HomogeneousPointsL1(1, 0) * HomogeneousPointsL1(0, 1)) '[a00*a11 - a10*a01]
5862+
HomogeneousEcuations(1, 0) = (HomogeneousPointsL2(0, 1) * HomogeneousPointsL2(1, 2)) - _
5863+
(HomogeneousPointsL2(1, 1) * HomogeneousPointsL2(0, 2))
5864+
HomogeneousEcuations(1, 1) = -1 * ((HomogeneousPointsL2(0, 0) * HomogeneousPointsL2(1, 2)) - _
5865+
(HomogeneousPointsL2(1, 0) * HomogeneousPointsL2(0, 2)))
5866+
HomogeneousEcuations(1, 2) = (HomogeneousPointsL2(0, 0) * HomogeneousPointsL2(1, 1)) - _
5867+
(HomogeneousPointsL2(1, 0) * HomogeneousPointsL2(0, 1))
5868+
'Compute the lines meet using Vectorial Matrix Products
5869+
EcuationsProduct(0, 0) = (HomogeneousEcuations(0, 1) * HomogeneousEcuations(1, 2)) - _
5870+
(HomogeneousEcuations(1, 1) * HomogeneousEcuations(0, 2)) '[a01*a12 - a11*a02]
5871+
EcuationsProduct(0, 1) = -1 * ((HomogeneousEcuations(0, 0) * HomogeneousEcuations(1, 2)) - _
5872+
(HomogeneousEcuations(1, 0) * HomogeneousEcuations(0, 2))) '-[a00*a12 - a10*a02]
5873+
EcuationsProduct(0, 2) = (HomogeneousEcuations(0, 0) * HomogeneousEcuations(1, 1) - _
5874+
(HomogeneousEcuations(1, 0) * HomogeneousEcuations(0, 1))) '[a00*a11 - a10*a01]
5875+
If EcuationsProduct(0, 2) = 0 Then
5876+
LinesIntersection = "#Null" 'Return a Null value. The lines meet at the infinity.
5877+
Else
5878+
Intersection(0, 0) = k * EcuationsProduct(0, 0) / EcuationsProduct(0, 2)
5879+
Intersection(0, 1) = k * EcuationsProduct(0, 1) / EcuationsProduct(0, 2)
5880+
LinesIntersection = Intersection
5881+
End If
5882+
End Function
5883+
5884+
''' <summary>
5885+
''' Returns the intersection point for two lines.
5886+
''' The lines must be given by two crossing points each
5887+
''' in array format, ex.:
5888+
''' {{x1;y1};{x2;y2}}; {{x3;y3};{x4;y4}}
5889+
''' </summary>
5890+
Private Function LinesIntersect(ByRef expression As String, ByRef fName As String) As String
5891+
Dim argsCount As Long
5892+
Dim tmpData() As String
5893+
Dim tmpEval As Variant
5894+
Dim LB As Long, UB As Long
5895+
5896+
On Error GoTo err_Handler
5897+
tmpData() = SplitArgs(expression)
5898+
LB = LBound(tmpData)
5899+
UB = UBound(tmpData)
5900+
argsCount = UB - LB + 1
5901+
Select Case argsCount
5902+
Case 2
5903+
Dim aArray() As Variant
5904+
ReDim aArray(0 To 1)
5905+
5906+
aArray(0) = ToDblArray(ArrayFromString(tmpData(LB)))
5907+
aArray(1) = ToDblArray(ArrayFromString(tmpData(UB)))
5908+
tmpEval = LinesIntersection(aArray(0), aArray(1))
5909+
If IsArray(tmpEval) Then
5910+
tmpEval = ArrayToString(tmpEval)
5911+
End If
5912+
Case Else
5913+
tmpEval = e_ValueError
5914+
BuildErrMessage errMissingArgsOrTooManyArgs, d_lCurly & fName & d_rCurly
5915+
End Select
5916+
LinesIntersect = tmpEval: Erase tmpData
5917+
Exit Function
5918+
err_Handler:
5919+
LinesIntersect = e_ValueError
5920+
BuildErrMessage errEvalError, d_lCurly & fName & d_rCurly & " | Error#: " & err.Number & d_Space & _
5921+
d_lParenthesis & err.Description & d_rParenthesis
5922+
End Function
5923+
57735924
Private Function LN(ByRef expression As String, ByRef fName As String) As String
57745925
On Error GoTo err_Handler
57755926
LN = CStr(Log(CDbl(expression)))
@@ -7978,7 +8129,7 @@ Private Function RegressionString(ByRef SolverResult() As Double, Optional ByRef
79788129
Dim strPNames As String
79798130
Dim m As Long
79808131
Dim n As Long
7981-
Dim o As Long
8132+
Dim O As Long
79828133
Dim s As Long
79838134

79848135
m = -1
@@ -7988,9 +8139,9 @@ Private Function RegressionString(ByRef SolverResult() As Double, Optional ByRef
79888139
strPNames = Join$(PredNames, P_SEPARATORCHAR)
79898140
End If
79908141
If Not IsNumeric(PredInteractions) Then n = UBound(PredInteractions)
7991-
o = UBound(SolverResult)
7992-
ReDim tmpNames(0 To o - 1)
7993-
For i = 0 To o - 1
8142+
O = UBound(SolverResult)
8143+
ReDim tmpNames(0 To O - 1)
8144+
For i = 0 To O - 1
79948145
If m >= 0 And n >= 0 Then
79958146
If s <= m Then
79968147
tmpNames(i) = PredNames(i)
@@ -7999,14 +8150,14 @@ Private Function RegressionString(ByRef SolverResult() As Double, Optional ByRef
79998150
tmpNames(i) = FormatNamedPredictors(strPNames, CStr(PredInteractions(i - s)), False)
80008151
End If
80018152
Else
8002-
If n + 1 - (o - i) >= 0 Then 'Save predictors relations without names
8003-
tmpNames(i) = PredInteractions(n + 1 - (o - i))
8153+
If n + 1 - (O - i) >= 0 Then 'Save predictors relations without names
8154+
tmpNames(i) = PredInteractions(n + 1 - (O - i))
80048155
Else
80058156
tmpNames(i) = "X" & CStr(i + 1)
80068157
End If
80078158
End If
80088159
Next i
8009-
For i = 0 To o
8160+
For i = 0 To O
80108161
If i = 0 Then
80118162
tmpResult = CStr(Round(SolverResult(i, 0), 4))
80128163
Else

0 commit comments

Comments
 (0)