Jump to content
Dohko

Point which get closer to another

Recommended Posts

Hello All

I'm trying to create a au3 script for get closer one point from another with iterations.

I'm bad at math, and I didn't succeed to create the GetCloser() Func (see below), if anyone have an idea... ^^ Ty

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.2
 Author:         myName

 Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
#include <Math.au3>
#include <MsgBoxConstants.au3>

;Best geometrical representation :)
;~                             |
;~                             |
;~                             |
;~          *B3                |                *B1
;~                             |
;~                             |
;~                             |
;~                             +1
;~ ----------------------..-1,*A +1,..-------------------------
;~                             -1
;~                             |
;~                             |
;~                             |
;~          *B4                |                *B2
;~                             |
;~                             |
;~                             |


Local $A[2]
Local $B1[2]
Local $B2[2]
Local $B3[2]
Local $B4[2]
$A[0] = 0
$A[1] = 0

;xB > xA & yB > yA (top right corner)
$B1[0] = 100
$B1[1] = 100

;xB > xA & yB < yA (bottom right corner)
$B2[0] = 100
$B2[1] = -100

;xB < xA & yB > yA (top left corner)
$B3[0] = -100
$B3[1] = 100

;xB < xA & yB < yA (bottom right corner)
$B4[0] = -100
$B4[1] = -100

;Same dist for all B points, its ok
Local $D1 = Distance($A,$B1);141
Local $D2 = Distance($A,$B2)
Local $D3 = Distance($A,$B3)
Local $D4 = Distance($A,$B4)
;MsgBox(0,"Dist A <-> B1",$D1)
;MsgBox(0,"Dist A <-> B2",$D2)
;MsgBox(0,"Dist A <-> B3",$D3)
;MsgBox(0,"Dist A <-> B4",$D4)

;get the new $A pos every ($D-20)
$step = 20

;141/6 Then 8 loops ?
While $D1 <> 0
   $A = GetCloser($A,$B1,$D1,$step)
   $D1 = Distance($A,$B1)
   MsgBox(0,"NEW POS","A = "&$A[0]&","&$A[1])
WEnd

 MsgBox(0,"Pos A = B","A = "&$A[0]&","&$A[1]&" B= "$B[0]&","$B[1])

;B2,B3,B4 loop laters....

Func Distance($A,$B)
   local $valeur = (($B[0]-$A[0])^2) + (($B[1]-$A[1])^2)
   $valeur = Sqrt($valeur)
   $valeur = Round($valeur,0)
   return $valeur
EndFunc

;Try to understand mathematics... :)
;~ Func Angle($A,$B)
;~    local $angle = _Degree(ATan(($B[1]-$A[1])/($B[0]-$A[0])))
;~    return $angle
;~ EndFunc

;I really dont know how to do this, I find this
;https://www.developpez.net/forums/d830412/general-developpement/algorithme-mathematiques/mathematiques/calcul-rapprocher-point-d/ (souviron34 answer)
Func GetCloser($A,$B,$D,$step)
   local $newPosA[2]

   ;x
   $newPosA[0] = -1;how to calcuate... ACos (or something like this?)
   ;y
   $newPosA[1] = -1;how to calcuate...ASin (or something like this?)

   ;I need this x/y pos
   return $newposA
EndFunc

 

Share this post


Link to post
Share on other sites

Can't remember where AutoIt measures 0 degrees from, but Cosine is +1 at 0 degrees and -1 at 180 degrees, Sine is +1 at 90 degrees, -1 at 270 degrees. Multiply by your radius by Sine to reduce/expand in the y direction, and by Cosine to reduce/expand in the x direction (I think). I think the trig functions use radians, so multiply the degrees by Pi/180 to convert.

Share this post


Link to post
Share on other sites

Post mentionned "simple"? Geez!

There is no need for trigonometry here:

Local $aPts = [ _
    [-1.58, 1.06], _        ; start point
    [6.06, 4.46], _         ; goal 1
    [-8.32, 7.44], _
    [6.22, -7.3], _
    [3.02, 6.36] _          ; goal 4
]

Local $Step = 5
For $i = 1 To 4
    _Walk($aPts[0][0], $aPts[0][1], $aPts[$i][0], $aPts[$i][1], $Step)
Next

; walk from point (x0, y0) to point (x1, y1) in n steps
Func _Walk($x0, $y0, $x1, $y1, $n)
    Local $dX = ($x1 - $x0) / $n, $dY = ($y1 - $y0) / $n
    For $i = 0 To $n
        ConsoleWrite('(' & Round($x0 + $dX * $i, 2) & '), (' & Round($y0 + $dY * $i, 2) & ')' & @LF)
    Next
    ConsoleWrite(@LF)
EndFunc

"Look 'Ma: no Cos()"


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

Hello all :)

Thx for all your comments, I'm able to find a way to achieve this.

The code is verbos and not optimise I think if anyone has idea to improve this :)

For jchd, I badly name my var $step but its not step but the distance to do for a loop (see ex below) : 

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.2
 Author:         myName

 Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
#include <Math.au3>
#include <MsgBoxConstants.au3>

;Best geometrical representation :)
;~                             |
;~                             |
;~                             |
;~          *B3                |                *B1
;~                             |
;~                             |
;~                             |
;~                             +1
;~ ----------------------..-1,*A +1,..-------------------------
;~                             -1
;~                             |
;~                             |
;~                             |
;~          *B4                |                *B2
;~                             |
;~                             |
;~                             |


Local $A[2]
Local $B1[2]
Local $B2[2]
Local $B3[2]
Local $B4[2]

;xB > xA & yB > yA (top right corner)
$B1[0] = 100
$B1[1] = 100

;xB > xA & yB < yA (bottom right corner)
$B2[0] = 100
$B2[1] = -100

;xB < xA & yB > yA (top left corner)
$B3[0] = -100
$B3[1] = 100

;xB < xA & yB < yA (bottom right corner)
$B4[0] = -100
$B4[1] = -100

;Same dist for all B points, its ok
Local $D1 = Distance($A,$B1);141
Local $D2 = Distance($A,$B2)
Local $D3 = Distance($A,$B3)
Local $D4 = Distance($A,$B4)
;MsgBox(0,"Dist A <-> B1",$D1)
;MsgBox(0,"Dist A <-> B2",$D2)
;MsgBox(0,"Dist A <-> B3",$D3)
;MsgBox(0,"Dist A <-> B4",$D4)

$DistToDo = 20
$A[0] = 0
$A[1] = 0
While $D1 <> 0
   $A = GetCloser($A,$B1,$D1,$DistToDo)
   $D1 = Distance($A,$B1)
   If $D1 <= $DistToDo Then
      $DistToDo = $D1
   EndIf

   MsgBox(0,"NEW POS","A = "&$A[0]&","&$A[1]&" DIST LEFT = "&$D1&" DISTTODO = "&$DistToDo)
WEnd

$DistToDo = 20
$A[0] = 0
$A[1] = 0
While $D2 <> 0
   $A = GetCloser($A,$B2,$D2,$DistToDo)
   $D2 = Distance($A,$B2)
   If $D2 <= $DistToDo Then
      $DistToDo = $D2
   EndIf

   MsgBox(0,"NEW POS","A = "&$A[0]&","&$A[1]&" DIST LEFT = "&$D2&" DISTTODO = "&$DistToDo)
WEnd

$DistToDo = 20
$A[0] = 0
$A[1] = 0
While $D3 <> 0
   $A = GetCloser($A,$B3,$D3,$DistToDo)
   $D3 = Distance($A,$B3)
   If $D3 <= $DistToDo Then
      $DistToDo = $D3
   EndIf

   MsgBox(0,"NEW POS","A = "&$A[0]&","&$A[1]&" DIST LEFT = "&$D3&" DISTTODO = "&$DistToDo)
WEnd

$DistToDo = 20
$A[0] = 0
$A[1] = 0
While $D4 <> 0
   $A = GetCloser($A,$B4,$D4,$DistToDo)
   $D4 = Distance($A,$B4)
   If $D4 <= $DistToDo Then
      $DistToDo = $D4
   EndIf

   MsgBox(0,"NEW POS","A = "&$A[0]&","&$A[1]&" DIST LEFT = "&$D4&" DISTTODO = "&$DistToDo)
WEnd

;~ ;Use Case *A not from origin
Local $ATopRight[2]
$ATopRight[0] = 20
$ATopRight[1] = 15
$DistToDo = 20
$D1 = Distance($ATopRight,$B1)
While $D1 <> 0
   $ATopRight = GetCloser($ATopRight,$B1,$D1,$DistToDo)
   $D1 = Distance($ATopRight,$B1)
   If $D1 <= $DistToDo Then
      $DistToDo = $D1
   EndIf

   MsgBox(0,"NEW POS","A = "&$ATopRight[0]&","&$ATopRight[1]&" DIST LEFT = "&$D1&" DISTTODO = "&$DistToDo)
WEnd

Local $ATopLeft[2]
$ATopLeft[0] = -33
$ATopLeft[1] = 72
$DistToDo = 20
$D1 = Distance($ATopLeft,$B1)
While $D1 <> 0
   $ATopLeft = GetCloser($ATopLeft,$B1,$D1,$DistToDo)
   $D1 = Distance($ATopLeft,$B1)
   If $D1 <= $DistToDo Then
      $DistToDo = $D1
   EndIf

   MsgBox(0,"NEW POS","A = "&$ATopLeft[0]&","&$ATopLeft[1]&" DIST LEFT = "&$D1&" DISTTODO = "&$DistToDo)
WEnd

Func Distance($A,$B)
   local $valeur = (($B[0]-$A[0])^2) + (($B[1]-$A[1])^2)
   $valeur = Sqrt($valeur)
   $valeur = Round($valeur,0)
   return $valeur
EndFunc

Func GetCloser($A,$B,$D,$DistToDo)
   local $newPosA[2]
   $newPosA[0] = $A[0]
   $newPosA[1] = $A[1]

   local $CurrentDist = Distance($newPosA,$B)

   While $CurrentDist >= ($D-$DistToDo) And $CurrentDist <> 0
      ;MsgBox(0,"","NEWPOS A x = "&$newPosA[0]&" B x "&$B[0])
      ;MsgBox(0,"","NEWPOS A y = "&$newPosA[1]&" B y "&$B[1])
      ;x
      If $newPosA[0] < $B[0] Then
         $newPosA[0] = $newPosA[0]+1
      ElseIf $newPosA[0] <> $B[0] Then
         $newPosA[0] = $newPosA[0]-1
      EndIf

      ;y
      If $newPosA[1] < $B[1]  Then
         $newPosA[1] = $newPosA[1]+1
      ElseIf $newPosA[1] <> $B[1] Then
         $newPosA[1] = $newPosA[1]-1
      EndIf

      $CurrentDist = Distance($newposA,$B)
   WEnd


   return $newposA
EndFunc

 

Share this post


Link to post
Share on other sites
Posted (edited)
3 hours ago, Dohko said:

I badly name my var $step but its not step but the distance to do for a loop

OK. Then it just needs a little change in initialization:

Local $aPts = [ _
    [-1.58, 1.06], _        ; start point
    [6.06, 4.46], _         ; goal 1
    [-8.32, 7.44], _
    [-6.22, -7.3], _
    [3.02, -6.36] _         ; goal 4
]

Local $StepDist = 3.84      ; distance to move at every step (except the last)
For $i = 1 To UBound($aPts) - 1
    _Walk($aPts[0][0], $aPts[0][1], $aPts[$i][0], $aPts[$i][1], $StepDist)
Next

; walk from point (x0, y0) to point (x1, y1) moving at most dist at each step
Func _Walk($x0, $y0, $x1, $y1, $dist)
    Local $Steps = Sqrt(($x1 - $x0) ^ 2 + ($y1 - $y0) ^ 2) / $dist
    Local $dX = ($x1 - $x0) / $Steps, $dY = ($y1 - $y0) / $Steps
    For $i = 0 To Floor($Steps)
        ConsoleWrite('(' & Round($x0 + $dX * $i, 2) & ', ' & Round($y0 + $dY * $i, 2) & ')' & @LF)
    Next
    ConsoleWrite('(' & $x1 & ', ' & $y1 & ')' & @LF)
    ConsoleWrite(@LF)
EndFunc

NOTE: there was a couple of sign errors of point coordinates in my previous post (I wanted to illustrate all four quadrants).

Here you can see the walks in all quadrants. Some distances display slightly in excess of the limit, but that's a cosmetic effect due to marginal floating-point rounding. And still no trigonometry is needed.

EDIT: you may have to check that the last step is indeed required. It is not needed if ever the distance to go is an integral multiple of the step distance (pretty unlikely in random real-world data). Simply test whether $Step = Int($Step)

Walks.jpg

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By lordofthestrings
      yeah finally finished my latest script. 
       as attachement Proof_of_Concept pic, & sourcecode + compiled exe in case you don't want to loook for the extra includes or something..
      Hope someone likes it :-)
      here's how to use it. simply run it, and use it as mousepointer (who doesn't want a geotriangle as cursor anyways?)
      when you want to use it inside for example paint,  press Q to quit following the mouse, if you want to close the application  just press escape.
      LEFT & Right rotate the geo triangle
      up freezes the rotation.
      down clears the image
      more features can be found in the code itself.
      best regards,
      Dimitri

      Triangle.zip
    • By czardas
      AutoMathEdit

      This is a very simple language written in AutoIt. AutoMathEdit only handles numeric operations and lacks the fexibility and functionality of other programming languages. it's still a language nonetheless! See this post:

      There are currently no keywords or loops, but the intended purpose of AutoMathEdit is to replace the calculator for quick tasks. The standard windows calculator does not keep tabs on every number you type. This is one advantage of using AutoMathEdit instead of using a standard calculator.

      This is the first scripting language I have ever written and it was certainly an education. I know I'm only scratching the surface with this, but everyone has to start soimewhere. I have gained much respect for the dev team after this endeavour. Dealing with so many complicated commands must be a nightmare.

      AutoMathEdit is meant to be used exclusivey within an Edit control. The function Echo behaves like the AutoIt function ConsoleWrite. This is an alpha release and there are still several bugs need ironing out.

      AutoMathEdit.au3

      #include-once #include <Math.au3> #include <Array.au3> ; #INDEX# ======================================================================================================================= ; Title .........: AutoMathEdit Version 0.0.0.6 (Alpha) ; AutoIt Version : 3.3.8.1 ; Language ......: English ; Description ...: Simple (maths only) scripting language based on AutoIt ; Notes .........: AutoMathEdit makes use of AutoIt syntax and standard maths functions. ; The library is not yet complete and this release is for evaluation purposes. ;+ ; Supported AutoIt functions:- Abs ACos ASin ATan BitAND BitNOT BitOR BitRotate ; BitShift BitXOR Cos Ceiling Dec Exp Floor Hex Log Mod Random Round Sin Sqrt ;+ ; Supported UDF functions:- _ATan2 _Combinations _Degree Echo _Factorial _Max _Min ; _Radian _Permutations ;+ ; Supported variable types:- integers floats binary ;+ ; Supported operators:- + - * / ^ = += -= *= /= ;+ ; Constants:- ; $MATH_E .... (Napiers Constant) ; $MATH_PHI .. (Golden Ratio) ; $MATH_PI ... (Pi) ; $MATH_PSI .. (Reciprocal Fibonacci Constant) ;+ ; Supported syntax:- ; 1. End of line comments (semicolon) ; 2. Line continuation (underscore) ;+ ; General Comments: ; UDF functions are included automatically. ; All variables are declared automatically. ; The use of $ (dollar sign) for variable names is optional. ; The function Echo returns the value of an expression. ; Echo(expression) ;= value ;+ ; Thanks to the following devs and members who's examples have been a great inspiration: ; Jon, Manadar, Mat, Valik, trancexx, UEZ (list is not complete) ;+ ; Author(s) .....: Nick Wilkinson (czardas) ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ;_Combinations ;_Execute ;_Factorial ;_Permutations ; =============================================================================================================================== ; #INTERNAL_USE_ONLY#============================================================================================================ ;__AssignSplit ;__ErrorMsg ;__GetBreakPoint ;__GetNewStr ;__GetSubArr ;__IsConst ;__IsFunc ;__IsReserved ;__Return ;__StripOutStrings ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _Execute ; Description ...: Runs AutoMathEdit ; Syntax.........: _Execute($_sScript_) ; Parameters ....: $_sScript_ .... The string to parse. ; Return values .: Success ....... Parses AutoMathEdit and returns the new code string. ; Failure ....... Parses AutoMathEdit up to the fail point and sets @error ; |@error = 1 ... Illegal characters ; |@error = 2 ... Invalid Syntax ; |@error = 3 ... Function not recognised ; |@error = 4 ... Unexpected Termination ; |@error = 5 ... Unterminated String ; |@error = 6 ... Failed to reassign mathematical constant ; |@error = 7 ... Missing Parentheses ; |@error = 8 ... Unassigned Variable ; Author ........: czardas ; Modified.......: ; Remarks .......: _Execute also handles calls to the Echo() function which evaluates an expression. ; The value returned by the function Echo appears as a comment in the returned code. ; Related .......: None ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _Execute($_sScript_) If Not StringLen($_sScript_) Then Return SetError(4, 0, $_sScript_) Local Const $MATH_E = 2.71828182845904523536028747135266249 ; Napiers Constant Local Const $MATH_PHI = 1.61803398874989484820458683436563811772 ; Golden Ratio Local Const $MATH_PI = 3.14159265358979323846264338328 ; Pi Local Const $MATH_PSI = 3.359885666243177553172011302918927179688905133731 ; Reciprocal Fibonacci constant Local $_aRawData_ = StringSplit(StringStripCR($_sScript_), @LF) $_sScript_ = StringRegExpReplace($_sScript_, "(;.*)", "") ; Remove comments Local $_subStr_ ; Substitute string for $ and to avoid conflicts with reserved variables or constants __GetNewStr($_sScript_, $_subStr_) Local $_aTemp_, $_error_, $_sFail_ = "" ; To store the string which could not be parsed $_aTemp_ = __GetSubArr($_sScript_, $_subStr_, $_sFail_) ; Returns an array of substitute patterns $_error_ = @error Local $_aScriptArr_, $foo, $_sRawCode_ = $_sScript_ ; Keep original code intact $_sScript_ = StringReplace($_sScript_, "$MATH", ";") ; To avoid corrupting constant variable names $_sScript_ = StringReplace($_sScript_, "$", $_subStr_) ; To avoid conflicts with duplicate variable names $_sScript_ = StringReplace($_sScript_, ";", "$MATH") ; Replace the correct math constant names If $_error_ = 0 Then For $foo = 1 To $_aTemp_[0][0] $_sScript_ = StringRegExpReplace($_sScript_, "(?i)(b" & $_aTemp_[$foo][0] & "b)", $_aTemp_[$foo][1]) Next Else If StringLen($_sFail_) Then $_aScriptArr_ = StringSplit(StringStripCR($_sScript_), @LF) ; Split to lines of raw code For $foo = 0 To UBound($_aScriptArr_) -1 If StringInStr($_aScriptArr_[$foo], $_sFail_) Then $_sFail_ = "Line " & $foo & @LF & $_sFail_ ExitLoop EndIf Next MsgBox(16, "Error", __ErrorMsg($_error_) & @LF & $_sFail_) Return SetError($_error_, 0, __Return($_aRawData_)) ; Unable to parse - Errors vary EndIf EndIf Local $bar ; Variable integer $_aScriptArr_ = StringSplit(StringStripCR($_sScript_), @LF) ; Split to lines of raw code For $foo = 1 To $_aScriptArr_[0] $bar = $foo While StringRegExp($_aScriptArr_[$foo], "(s_s*z)") ; Check for line continuation underscore NOT CHECKED If $bar < $_aScriptArr_[0] Then If StringLen($_aScriptArr_[$bar +1]) Then $_aScriptArr_[$foo] = StringRegExpReplace($_aScriptArr_[$foo], "(s_s*z)", " " & $_aScriptArr_[$bar +1]) $_aScriptArr_[$bar +1] = "" $bar += 1 Else MsgBox(16, "Error", "Line " & $bar & @LF & __ErrorMsg(5) & @LF & $_aRawData_[$bar]) Return SetError(5, 0, __Return($_aRawData_)) ; Unterminated String EndIf ElseIf StringRegExp($_aScriptArr_[$foo], "(s_s*z)") Then MsgBox(16, "Error", "Line " & $_aScriptArr_[0] & @LF & __ErrorMsg(5)) Return SetError(5, 0, __Return($_aRawData_)) ; Unterminated String EndIf WEnd $foo = $bar Next For $foo = 1 To $_aScriptArr_[0] ; Parse each line sequence $_aScriptArr_[$foo] = StringStripWS($_aScriptArr_[$foo], 3) If Not StringLen($_aScriptArr_[$foo]) Then ContinueLoop If StringInStr($_aScriptArr_[$foo], "=") Then $_aAssign_ = __AssignSplit($_aScriptArr_[$foo]) $_error_ = @error If $_error_ = 0 Then If StringLeft($_aAssign_[1], 1) = "$" Then $_aAssign_[1] = StringTrimLeft($_aAssign_[1], 1) Else MsgBox(16, "Error", __ErrorMsg(2) & @LF & "Line " & $foo & @LF & $_aRawData_[$foo]) Return SetError(2, 0, __Return($_aRawData_)) EndIf If __IsConst($_aAssign_[1]) Then MsgBox(16, "Error", __ErrorMsg(6) & @LF & "Line " & $foo & @LF & "$" & $_aAssign_[1] & " =") Return SetError(6, 0, __Return($_aRawData_)) EndIf $_aAssign_[2] = Execute($_aAssign_[2]) $_error_ = @error If StringLen($_aAssign_[2]) = 0 Or ($_aAssign_[2] <> 0 And $_error_ <> 0 And Not IsNumber(Number($_aAssign_[2])) Or $_aAssign_[2] = False) Then MsgBox(16, "Error", __ErrorMsg(2) & @LF & "Line " & $foo & @LF & $_aAssign_[1] & " =") Return SetError(2, 0, __Return($_aRawData_)) EndIf If $_aAssign_[0] = 2 Then Assign($_aAssign_[1], $_aAssign_[2]) ElseIf IsDeclared($_aAssign_[1]) Then $_nValue_ = Execute("$" & $_aAssign_[1]) Switch $_aAssign_[0] Case "+" Assign($_aAssign_[1], $_nValue_ + $_aAssign_[2]) Case "-" Assign($_aAssign_[1], $_nValue_ - $_aAssign_[2]) Case "*" Assign($_aAssign_[1], $_nValue_ * $_aAssign_[2]) Case "/" Assign($_aAssign_[1], $_nValue_ / $_aAssign_[2]) EndSwitch Else MsgBox(16, "Error", __ErrorMsg(8) & @LF & "Line " & $foo & @LF & $_aRawData_[$foo]) Return SetError(8, 0, __Return($_aRawData_)) EndIf Else $bar = __GetBreakPoint($_sRawCode_, $foo, "=", 2) MsgBox(16, "Error", __ErrorMsg(2) & @LF & "Line " & $bar & @LF & "=") Return SetError(2, 0, __Return($_aRawData_)) EndIf ; Echo is an internal command which writes the value of an expression. ElseIf StringLeft($_aScriptArr_[$foo], 4) = "Echo" Then $_aScriptArr_[$foo] = StringStripWS(StringTrimLeft($_aScriptArr_[$foo], 4), 3) If StringLeft($_aScriptArr_[$foo], 1) <> "(" Then MsgBox(16, "Error", __ErrorMsg(7) & @LF & "Line " & $foo & @LF & $_aRawData_[$foo]) Return SetError(7, 0, __Return($_aRawData_)) ; Missing Parentheses EndIf $bar = __GetBreakPoint($_sRawCode_, $foo) If StringRight($_aScriptArr_[$foo], 1) <> ")" Then MsgBox(16, "Error", __ErrorMsg(7) & @LF & "Line " & $bar & @LF & $_aRawData_[$bar]) Return SetError(7, 0, __Return($_aRawData_)) ; Missing Parentheses EndIf $_aScriptArr_[$foo] = StringTrimLeft(StringTrimRight($_aScriptArr_[$foo], 1), 1) $_temp_ = Execute($_aScriptArr_[$foo]) $_error_ = @error If StringLen($_temp_) = 0 Or ($_temp_ <> 0 And $_error_ <> 0 And (Not IsNumber(Number($_temp_)) Or $_temp_ = False)) Then $_aTemp_ = StringRegExp($_aScriptArr_[$foo], "x24w+", 3) If Not @error Then For $bar = 0 To UBound($_aTemp_) -1 $_temp_ = StringTrimLeft($_aTemp_[$bar], 1) If Not IsDeclared($_temp_) Then $_subLen_ = StringLen($_subStr_) If StringLeft($_temp_, $_subLen_ +1) = "k" & $_subStr_ Then ; Or StringLeft($_temp_, $_subLen_ +1) = "n" & $_subStr_ ; may need to add this $_temp_ = StringTrimLeft($_temp_, $_subLen_ +1) ElseIf StringLeft($_temp_, $_subLen_) = $_subStr_ Then $_temp_ = StringTrimLeft($_temp_, $_subLen_) EndIf $bar = __GetBreakPoint($_sRawCode_, $foo, $_temp_) MsgBox(16, "Error", __ErrorMsg(8) & @LF & "Line " & $bar & @LF & $_aRawData_[$bar]) Return SetError(8, 0, __Return($_aRawData_)) EndIf Next EndIf MsgBox(16, "Error", __ErrorMsg(2) & @LF & "Line " & $foo & @LF & $_aRawData_[$foo]) Return SetError(2, 0, __Return($_aRawData_)) EndIf $_aRawData_[$bar] = StringStripWS(StringRegExpReplace($_aRawData_[$bar], "(;.*)", ""), 2) & " ;= " & $_temp_ Else ; No assignments or Echo function - just an expression. What's that all about? $_temp_ = Execute($_aScriptArr_[$foo]) $_error_ = @error If StringLen($_temp_) = 0 Or ($_temp_ <> 0 And $_error_ <> 0 And Not IsNumber(Number($_temp_)) Or $_temp_ = False) Then MsgBox(16, "Error", __ErrorMsg(2) & @LF & "Line " & $foo & @LF & $_aRawData_[$foo]) Return SetError(2, 0, __Return($_aRawData_)) EndIf EndIf Next Return __Return($_aRawData_) EndFunc ;==> _Execute ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __GetNewStr ; Description ...: Searches for a nonconflicting substitution string to replace the dollar sign. ; Syntax.........: __GetNewStr($sTestStr, ByRef $sNewString) ; Parameters ....: $sTestStr - AutoMathEdit ; : $sNewString - substitution string ; Return values .: [ByRef] $sNewString ; Author ........: czardas ; Modified.......: ; Remarks .......: Avoids conflicts by placing underscore in the second character position. ; Related .......: __GetSubArr ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __GetNewStr($sTestStr, ByRef $sNewString) ; Find a nonconflicting replacement for $ (dollar sign) Local $aChar[37] = ["_","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] ; Move outside function If StringLen($sNewString) < 2 Then $sNewString = $aChar[Random(0, 36, 1)] & "_" If Not StringInStr($sTestStr, $sNewString) Then Return For $i = 0 To 36 If Not StringInStr($sTestStr, $sNewString & $aChar[$i]) Then $sNewString &= $aChar[$i] Return EndIf Next $sNewString &= $aChar[Random(0, 36, 1)] __GetNewStr($sTestStr, $sNewString) EndFunc ;==> __GetNewStr ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __GetSubArr ; Description ...: Searches for a nonconflicting substitution string to replace the dollar sign. ; Syntax.........: __GetNewStr($sTestStr, ByRef $sNewString) ; Parameters ....: $sTestStr - AutoMathEdit ; : $subStr - substitution string ; : $sFail - Unexpected string which caused the function to fail ; ; Return values .: Success - An array of variable name substitutions ; Failure - Sets @error and returns [ByRef] $sFail ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: __GetNewStr ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __GetSubArr($sTestStr, $subStr, ByRef $sFail) __StripOutStrings($sTestStr) ; Remove quotes Local $aRegExp = StringRegExp($sTestStr, "[^,w=-^*+()x24s.x22'/]", 3) If Not @error Then ; Encountered an illegal character $sFail = $aRegExp[0] Return SetError(1) ; Illegal character EndIf $aRegExp = StringRegExp($sTestStr, "([w|x24]x24)|(x24[^w])", 3) If Not @error Then ; Dollar is in the wrong place $sFail = $aRegExp[0] Return SetError(2) ; Invalid Syntax EndIf $aRegExp = StringRegExp($sTestStr, "($?w+s*(?)", 3) ; Gets functions and variables If IsArray($aRegExp) Then For $i = 0 To UBound($aRegExp) -1 $aRegExp[$i] = StringLower(StringStripWS($aRegExp[$i], 3)) ; Account for case insensitivity Next $aRegExp = _ArrayUnique($aRegExp) ; Get rid of duplicated substitution strings Local $aSubArr[UBound($aRegExp) +1][2] $aSubArr[0][0] = 0 For $i = 0 To UBound($aRegExp) -1 $aRegExp[$i] = StringStripWS($aRegExp[$i], 2) Select Case StringRight($aRegExp[$i], 1) = "(" If StringLeft($aRegExp[$i], 1) = "$" Then ; Functions do not begin with $ $sFail = $aRegExp[$i] Return SetError(2) ; Invalid Syntax ElseIf Not (__IsFunc(StringRegExpReplace($aRegExp[$i], "s*(", "")) Or StringStripWS($aRegExp[$i], 8) = "_(") Then $sFail = $aRegExp[$i] Return SetError(3) ; Function not recognised EndIf Case StringLeft($aRegExp[$i], 1) = "$" If __IsReserved(StringTrimLeft($aRegExp[$i], 1)) Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = StringReplace($aRegExp[$i], "$", "$r" & $subStr) ElseIf Not __IsConst(StringTrimLeft($aRegExp[$i], 1)) Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = StringReplace($aRegExp[$i], "$", "$o" & $subStr) EndIf Case StringLeft($aRegExp[$i], 2) = "0x" If Not StringIsXDigit(StringTrimLeft($aRegExp[$i], 2)) Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = "$x" & $subStr & $aRegExp[$i] EndIf Case Not (StringIsInt($aRegExp[$i]) Or StringIsFloat($aRegExp[$i]) Or __IsFunc($aRegExp[$i])) If __IsReserved($aRegExp[$i]) Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = "$r" & $subStr & $aRegExp[$i] ElseIf __IsConst($aRegExp[$i]) Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = "$k" & $subStr & $aRegExp[$i] ElseIf StringIsDigit(StringLeft($aRegExp[$i], 1)) Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = "$d" & $subStr & $aRegExp[$i] ElseIf $aRegExp[$i] <> "_" Then $aSubArr[0][0] += 1 $aSubArr[$aSubArr[0][0] ][0] = $aRegExp[$i] $aSubArr[$aSubArr[0][0] ][1] = "$w" & $subStr & $aRegExp[$i] EndIf EndSelect Next ReDim $aSubArr[$aSubArr[0][0] +1][2] For $i = 0 To $aSubArr[0][0] $aSubArr[$i][0] = StringReplace($aSubArr[$i][0], "$", $subStr) Next Return $aSubArr ; No errors have occured. Else Return SetError(4) ; Unexpected Termination EndIf EndFunc ;==> __GetSubArr ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __StripOutStrings ; Description ...: Removes all strings wrapped in quotes from the code. ; Syntax.........: __StripOutStrings(ByRef $sCodeStr) ; Parameters ....: $sCodeStr - The string to alter. ; Return values .: [ByRef] the string after removing all strings wrapped in quotes ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: None ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __StripOutStrings(ByRef $sCodeStr) Local $foo, $bar, $iStart, $iEnd, $aQuot While 1 $foo = StringInStr($sCodeStr, '"') ; Double quote $bar = StringInStr($sCodeStr, "'") ; Single quote If $foo = 0 And $bar = 0 Then ExitLoop If $foo > $bar And $bar > 0 Then $iStart = $bar $sQuot = "'" Else $iStart = $foo $sQuot = '"' EndIf $iEnd = StringInStr($sCodeStr, $sQuot, 0, 2) If $iEnd = 0 Then ; Error Code??? $sCodeStr = StringLeft($sCodeStr, $iStart -1) Else $sCodeStr = StringLeft($sCodeStr, $iStart -1) & " " & StringRight($sCodeStr, StringLen($sCodeStr) - $iEnd) EndIf WEnd EndFunc ;==> __StripOutStrings ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __IsConst ; Description ...: Checks to see if the string is the name of a constant. ; Syntax.........: __IsFunc($sTestStr) ; Parameters ....: $sTestStr - Variable name to test ; Return values .: Returns True or False ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: __IsFunc , __IsReserved ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __IsConst($sTestStr) $sTestStr = "|" & $sTestStr & "|" If StringInStr("|MATH_E|MATH_PHI|MATH_PI|MATH_PSI|", $sTestStr) Then Return True Else Return False EndIf EndFunc ;==> __IsConst ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __IsFunc ; Description ...: Checks to see if the string is the name of a function. ; Syntax.........: __IsFunc($sTestStr) ; Parameters ....: $sTestStr - Name to test ; Return values .: Returns True or False ; Author ........: czardas ; Modified.......: ; Remarks .......: Only recognises AutoMathEdit functions ; Related .......: __IsConst , __IsReserved ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __IsFunc($sTestStr) $sTestStr = "|" & $sTestStr & "|" If StringInStr("|_ATan2|_Combinations|_Degree|_Factorial|_Max|_Min|_Permutations|_Radian|Abs|ACos|ASin|ATan|BitAND|BitNOT|BitOR|BitRotate|BitShift|BitXOR|Ceiling|Cos|Dec|Echo|Exp|Floor|Hex|Log|Mod|Random|Round|Sin|Sqrt|Tan|", $sTestStr) Then Return True Else Return False EndIf EndFunc ;==> __IsFunc ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __IsReserved ; Description ...: Checks to see if the variable name is already being used. ; Syntax.........: __IsReserved($sTestStr) ; Parameters ....: $sTestStr - Variable name to test ; Return values .: Returns True or False ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: __IsConst , __IsFunc ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __IsReserved($sTestStr) $sTestStr = "|" & $sTestStr & "|" If StringInStr("|_subStr_|_in|no_|_error_|_sFail_|_sRawCode_|_aAssign_|_nValue_|_sScript_|_temp_|_aTemp_|_subLen_|_aScriptArr_|_aRawData_|", $sTestStr) Then Return True Else Return False EndIf EndFunc ;==> __IsReserved ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __AssignSplit ; Description ...: Splits an assignment command to var = expression ; Syntax.........: __AssignSplit($sAssignStr) ; Parameters ....: $sAssignStr - Line of code containing an assignment operator ; Return values .: An array where:- ; | element 0 = type of assignment = += -= *= /= ; | element 1 = variable name ; | element 2 = expression ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: None ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __AssignSplit($sAssignStr) Local $aAssignArr = StringSplit($sAssignStr, "=") ; Split string => variable equals expression If $aAssignArr[0] > 2 Then Return SetError(2, 0, 0) ; Only one assignment allowed per line Switch StringRight($aAssignArr[1], 1) Case "+","-","*","/" ; Get type of assignment $aAssignArr[0] = StringRight($aAssignArr[1], 1) ; += or -= or *= or /= $aAssignArr[1] = StringTrimRight($aAssignArr[1], 1) Case Else If StringRegExp($aAssignArr[1], "([+-*/][s]+z)") Then Return SetError(2) EndSwitch $aAssignArr[1] = StringStripWS($aAssignArr[1], 3) Return $aAssignArr EndFunc ;==> __AssignSplit ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __GetBreakPoint ; Description ...: Determines the exact line where a break in operations occurs - an error or a closing bracket for Echo ; Syntax.........: __GetBreakPoint($scriptStr, $iPosition [, $sErrorStr = False [, $iOccurence = 1 ]] ) ; Parameters ....: $scriptStr - AutoMathEdit ; : $iPosition - Line to start the search ; : $sErrorStr - Unexpected string which caused the function to fail ; : $iOccurence - The occurence of the error string to find. ; Return values .: The line number from the original script where the break in operations occured. ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: None ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __GetBreakPoint($scriptStr, $iPosition, $sErrorStr = False, $iOccurence = 1) Local $aScriptArr = StringSplit(StringStripCR($scriptStr), @LF), $iCount = 0 Switch $sErrorStr Case "=" For $i = $iPosition To $aScriptArr[0] If StringRegExp($aScriptArr[$i], "(s_s*z)") Then While StringInStr($aScriptArr[$i], $sErrorStr, 0, 1) $aScriptArr[$i] = StringReplace($aScriptArr[$i], $sErrorStr, "", 1) $iCount += 1 If $iCount = $iOccurence Then Return $i WEnd Else Return $i EndIf Next Case False While StringRegExp($aScriptArr[$iPosition], "(s_s*z)") $iPosition += 1 If $iPosition > $aScriptArr[0] Or $aScriptArr[$iPosition -1] = "" Then Return SetError (5, 0, $iPosition) ; Unterminated string WEnd Return $iPosition Case Else For $iPosition = $iPosition To $aScriptArr[0] If StringRegExp($aScriptArr[$iPosition], "(x24" & $sErrorStr &"[^w])") Or StringRegExp($aScriptArr[$iPosition], "([^w]" & $sErrorStr &"[^w])") Then Return $iPosition Next EndSwitch EndFunc ;==> __GetBreakPoint ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __ErrorMsg ; Description ...: Returns the details of an error encountered while parsing the script. ; Syntax.........: __ErrorMsg($vError) ; Parameters ....: $vError - Error code 1 - 8 ; Return values .: $vError - Details of the type of error encountered. ; Author ........: czardas ; Modified.......: ; Remarks .......: ; Related .......: None ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __ErrorMsg($vError) Switch $vError Case 1 $vError = "Illegal characters" Case 2 $vError = "Invalid Syntax" Case 3 $vError = "Function not recognised" Case 4 $vError = "Unexpected Termination" Case 5 $vError = "Unterminated String" Case 6 $vError = "Failed to reassign mathematical constant" Case 7 $vError = "Missing Parentheses" Case 8 $vError = "Unassigned Variable" EndSwitch Return $vError EndFunc ;==> __ErrorMsg ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __Return ; Description ...: Same as _ArrayToString, but with parameters already set ; Syntax.........: __Return($aRawData) ; Parameters ....: $aRawData - an array with the original script plus added comments. ; Return values .: Original script plus comments. ; Author ........: czardas ; Modified.......: ; Remarks .......: This function only exists to simplify reading the code for _Execute. ; Related .......: None ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func __Return($aRawData) Return _ArrayToString($aRawData, @CRLF, 1) EndFunc ;==> __Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #region ;... External library not yet complete Func _Permutations($n, $k) If Not IsInt($n) Or Not IsInt($k) Then Return SetError(1) If $k > $n Then Return 0 Return _Factorial($n)/(_Factorial($n -$k)) EndFunc ;==> _Permutations Func _Combinations($n, $k) If Not IsInt($n) Or $n < 1 Or Not IsInt($k) Or $k < 1 Then Return SetError(1) If $k > $n Then Return 0 Return _Factorial($n)/(_Factorial($k)*_Factorial($n -$k)) EndFunc ;==> _Combinations Func _Factorial($n) ; From UEZ If Not IsInt($n) Or $n < 1 Then Return SetError(1) Local $iRet = 1 For $i = 1 to $n $iRet *= $i Next Return $iRet EndFunc #endregion
      Test Edit Control

      #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <GuiEdit.au3> #include <WinAPI.au3> #include <AutoMathEdit.au3> _MathEditorTest() Func _MathEditorTest() Local $hGUI = GUICreate("AutoMathScript Edit Control Test", 600, 400, Default, Default, BitOR($WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED)) Local $hFileMenu = GUICtrlCreateMenu("File") Local $hExit = GUICtrlCreateMenuItem("Exit", $hFileMenu), _ $hTools = GUICtrlCreateMenu("Tools") Local $hExecute = GUICtrlCreateMenuItem("Execute" & @TAB & "F5", $hTools), _ $iyOffset = _WinAPI_GetSystemMetrics(55) ; SM_CYMENUSIZE Local $hEdit1 = GUICtrlCreateEdit("", 0, 0, 600, 400 - $iyOffset, BitOr($GUI_SS_DEFAULT_EDIT, $ES_NOHIDESEL)), _ $hF5 = GUICtrlCreateDummy(), _ $hTab = GUICtrlCreateDummy(), _ $hSelectAll = GUICtrlCreateDummy(), _ $AccelKeys[3][2] = [[ @TAB, $hTab],["^a", $hSelectAll],["{F5}", $hF5]] GUICtrlSetFont($hEdit1, 12, 400, 1, "Lucida Console") GUISetAccelerators($AccelKeys) GUISetState() While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE, $hExit ExitLoop Case $hExecute, $hF5 $sRet = _Execute(_GetSelectedText($hEdit1)) _GUICtrlEdit_ReplaceSel($hEdit1, $sRet) Case $hTab _TAB($hEdit1) Case $hSelectAll _SelectAll($hEdit1) EndSwitch WEnd EndFunc ;==> _MathEditorTest Func _GetSelectedText($hEdit) Local $aPos = _GUICtrlEdit_GetSel($hEdit) If $aPos[0] = $aPos[1] Then Return SetError(1, 0, "") ; Nothing selected $sRet = StringMid(_GUICtrlEdit_GetText($hEdit), $aPos[0] +1, $aPos[1] - $aPos[0]) Return $sRet EndFunc ;==> _GetSelectedText Func _TAB($hEdit) Local $sSelText = _GetSelectedText($hEdit) If Not @error Then Local $aLines = StringSplit($sSelText, @CRLF, 1) If $aLines[0] > 1 Then For $i = 1 To $aLines[0] $aLines[$i] = @TAB & $aLines[$i] Next _GUICtrlEdit_ReplaceSel($hEdit, _ArrayToString($aLines, @CRLF, 1)) Return EndIf EndIf _GUICtrlEdit_ReplaceSel($hEdit, @TAB) EndFunc ;==> _TAB Func _SelectAll($hEdit) _GUICtrlEdit_SetSel($hEdit, 0, -1) EndFunc ;==> _SelectAll
      See next post for features, history and AutoMathEdit examples.
×
×
  • Create New...