Что нового

Мышь, клавиатура Движение курсора по дуге через 3 точки

svorky

Новичок
Сообщения
1
Репутация
0
Добрый день!
Уже несколько дней бьюсь с алгоритмом и без каких-то костылей нормально сделать не получается, пересмотрел кучу формул и уже совсем запутался.
Задача такая: юзер кликает на экране в начальную точку A, затем в финишную точку B, и промежуточную точку C. Скрипт шагами ведет курсор мыши по этой дуге из точки А в точку В через точку С, делая в каждом шаге клик, включая А и В, С не обязательно.
Как я вижу, проблема заключается в том, что большинство формул в интернете для пространства, где точка (0,0) в левом нижнем углу, в отличие от экрана монитора, где она наверху. Соответственно, неправильно определяются углы точек. Пробовал делать координату Y отрицательной, но в геометрии я не силён и что ещё нужно менять я не понимаю.
Основные функции у меня есть такие
Код:
#include <Math.au3>
#include <Misc.au3>
#include <Date.au3>

Func GetSegmentLength($x1, $y1, $x2, $y2)
  Return Sqrt(($x2 - $x1)^2 + ($y2 - $y1)^2)
EndFunc

; Вычисление радиуса и центра окружности по перпендикулярам
Func GetRadius($A, $B, $C)
   $m1 = ($C[1]-$A[1]) / ($C[0]-$A[0])
   $m2 = ($C[1]-$B[1]) / ($C[0]-$B[0])

   $x  = ($m1*$m2*($A[1]-$B[1])+$m2*($A[0]+$C[0])-$m1*($B[0]+$C[0])) / (2*($m2-$m1))
   $y  = (-1/$m1)*($x-($A[0]+$C[0])/2)+($A[1]+$C[1])/2

   $r  = Sqrt(($x-$A[0])^2+($y-$A[1])^2)
   Local $q[3] = [$r, $x, $y]
  Return $q
EndFunc


Func _ATan2(Const $nY, Const $nX)

    If Not IsNumber($nY) Or Not IsNumber($nX) Then Return SetError(1, 0, 0)

    Return SetError(0, 0, ATan($nY / $nX) + ((($nY <= 0) And ($nX < 0)) + (($nY > 0) And ($nX < 0)) - 2 * (($nY < 0) And ($nX < 0))) * 3.14159265358979323846)

EndFunc

Func getAngle2PointsDeg($p1_x, $p1_y, $p2_x, $p2_y)
   $pi = 4 * ATan(1)
  return ACos( ( ($p1_x * $p2_x) + ($p1_y * $p2_y) ) / (Sqrt($p1_x^2 + $p1_y^2) * sqrt($p2_x^2 + $p2_y^2)) ) * 180 / $pi
EndFunc

Func arcDraw($clockwise = 0)
   Local $A
   Local $B
   Local $C

   SplashTextOn("Рисование дуги по трём точкам", "Наведите мышь на 1-ю точку и нажмите пробел...", 300, 180, 40, 300, 4+16, "", 14)
   While 1
      If _IsPressed("20") Then
         While _IsPressed("20") = 1
         WEnd
         Send("{SPACE} up")
         $A = MouseGetPos()
         $x1 = $A[0]
         $y1 = $A[1]
         ExitLoop
      EndIf
      Sleep(100)
   WEnd
   SplashTextOn("Рисование дуги по трём точкам", "Наведите мышь на 2-ю точку и нажмите пробел...", 300, 180, 40, 300, 4+16, "", 14)
   ;ControlSetText("Рисование дуги по трём точкам", "", "Static1", "Наведите мышь на 2-ю точку и нажмите пробел...")
   While 1
      If _IsPressed("20") Then
         While _IsPressed("20") = 1
         WEnd
         Send("{SPACE} up")
         $B = MouseGetPos()
         $x2 = $B[0]
         $y2 = $B[1]
         ExitLoop
      EndIf
      Sleep(100)
   WEnd
   SplashTextOn("Рисование дуги по трём точкам", "Наведите мышь на 3-ю точку и нажмите пробел...", 300, 180, 40, 300, 4+16, "", 14)
   While 1
      If _IsPressed("20") Then
         Send("{SPACE} up")
         $C = MouseGetPos()
         $x3 = $C[0]
         $y3 = $C[1]
         ExitLoop
      EndIf
      Sleep(100)
   WEnd

   $l = GetSegmentLength($A[0], $A[1], $B[0], $B[1])
   $r = GetRadius($A, $B, $C)
   $Ox = $r[1]
   $Oy = $r[2]
   $radius = $r[0]

   $pi = 4 * ATan(1)

   $AAngle = _Atan2($A[1] - $Oy, $A[0] - $Ox) * (180/$pi)
   $BAngle = _Atan2($B[1] - $Oy, $B[0] - $Ox) * (180/$pi)

   $step = $pi
   moveMouseCircle($Ox, $Oy, $radius, 0, $AAngle, $BAngle, 100, $step)
   SplashOff()
EndFunc

Func moveMouseCircle($h, $k, $radius, $direction = 0, $startangle = 0, $endangel = 360, $delay = 10, $step = 50)
    ;h = Center X
    ;k = Center Y
    ;radius in pixels
    ;direction: 0 = clockwise (default), 1 = counter-clockwise
    ;start angle in degrees (0-360): default is 0
    ;delay in milliseconds: default 10
    ;step in degrees: default 0

    $pi = 4 * ATan(1)

   $start = $startangle
   $end = $endange
    ;For $Z = 1 to 2
        For $A = $start to $end Step $step
            If $direction Then
                $X = $h - sin(_Radian($A)) * $radius
            Else
                $X = $h + sin(_Radian($A)) * $radius
            EndIf
            $Y = $k - cos(_Radian($A)) * $radius
            MouseMove ( $X, $Y, 0)
            MouseClick("left")
            Sleep($delay)
        Next
        $start = 0
        $end = $startangle
    ;Next

EndFunc

Прошу помочь с дописанием скрипта и добавить код для рисования дуги против часовой стрелки (будет передаваться аргументом в функцию arcDraw)

На просторах ещё нашёл такую функцию определения углов, но адаптировать без костылей и велосипедов не получилось.
Код:
Func AnglePointToPoint($fromX, $fromY, $toX, $toY)
   $pi = 4 * ATan(1)
   $distanceX     = $toX - $fromX
   $distanceY     = -($toY - $fromY)
   $beta          = acos( abs($distanceX) / sqrt( $distanceX^2 + $distanceY^2 ) ) * 180 / $pi
   ConsoleWrite(_NowTime() & " -- dx = $distanceX$" & @CRLF)
   ConsoleWrite(_NowTime() & " -- dy = $distanceY$" & @CRLF)
   ConsoleWrite(_NowTime() & " -- beta = $beta$" & @CRLF)
   $angleResult   = 0.0

    if $distanceX > 0 Then
        if $distanceY < 0 Then
            $angleResult = $beta + 90;//right_bot
         else
            $angleResult = abs($beta - 90);//right_top
         EndIf
    else
        if $distanceY < 0 then
            $angleResult = abs($beta - 90) + 180;//left_bot
         else
            $angleResult = $beta + 270;//left_top
        EndIf
    EndIf
    return $angleResult
EndFunc
 
Верх