Jump to content

Check if a point is within various defined closed shapes.


Malkey
 Share

Recommended Posts

I think I misunderstood what you meant by a line function Malkey. I've had another play and here is an example of detecting if a point is within an enclosed shape.

The shape is only straight lines and circular arcs. I modified my _IsPtInArc function because I don't think it was correct, and I've altered the way it was used and simplified it.

It has a problem which I expected that it detects the end of a line twice so I will have to work out how to deal with that, but it's fairly close otherwise.

;using code by Malkey see http://www.autoitscript.com/forum/index....=&showtopic=89034&view=findpos
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $a1, $a2
Global $pi = 4 * ATan(1)
Global $Deg2Rad = 180 / $pi

Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic

_Main()

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 380
    Local $aPoints[11][8], $aTriangle[5][2]
    Local $hButton
    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)

    GUISetState()

    _GDIPlus_Startup()
    ;Double Buffer
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    ;End Double Buffer add-on 1 of 3

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

;set data in array for shape
    $aPoints[0][0] = 10; Number of  lines of Polygon
    $aPoints[1][0] = 1;st line
    $aPoints[1][1] = 10;x1
    $aPoints[1][2] = 30;y1
    $aPoints[1][3] = 10;x2
    $aPoints[1][4] = 290;y2

    $aPoints[2][0] = 2; arc
    $aPoints[2][1] = 30;center x
    $aPoints[2][2] = 290;centre y
    $aPoints[2][3] = 20;rad
    $aPoints[2][4] = 180;st angle
    $aPoints[2][5] = -90; sweep

    $aPoints[3][0] = 1;st line
    $aPoints[3][1] = 30;
    $aPoints[3][2] = 310
    $aPoints[3][3] = 190;
    $aPoints[3][4] = 310

    $aPoints[4][0] = 2; arc
    $aPoints[4][1] = 190;center x
    $aPoints[4][2] = 290;center y
    $aPoints[4][3] = 20;rad
    $aPoints[4][4] = 90;st angle
    $aPoints[4][5] = -90; sweep

    $aPoints[5][0] = 1;st line
    $aPoints[5][1] = 210;
    $aPoints[5][2] = 290
    $aPoints[5][3] = 210;
    $aPoints[5][4] = 230

    $aPoints[6][0] = 2; arc
    $aPoints[6][1] = 250;center x
    $aPoints[6][2] = 230;center y
    $aPoints[6][3] = 40;rad
    $aPoints[6][4] = 180;st angle
    $aPoints[6][5] = 90; sweep

    $aPoints[7][0] = 2; arc
    $aPoints[7][1] = 250;center x
    $aPoints[7][2] = 100;center y
    $aPoints[7][3] = 90;rad
    $aPoints[7][4] = 90;st angle
    $aPoints[7][5] = -180;sweep

    $aPoints[8][0] = 1;st line
    $aPoints[8][1] = 250;
    $aPoints[8][2] = 10
    $aPoints[8][3] = 30;
    $aPoints[8][4] = 10

    $aPoints[9][0] = 2; arc - closes shape
    $aPoints[9][1] = 30;center x
    $aPoints[9][2] = 30;center y
    $aPoints[9][3] = 20;rad
    $aPoints[9][4] = 270; st angle
    $aPoints[9][5] = -90; sweep

    $aPoints[10][0] = 2; arc - closes shape
    $aPoints[10][1] = 130;center x
    $aPoints[10][2] = 130;center y
    $aPoints[10][3] = 40;rad
    $aPoints[10][4] = 0; st angle
    $aPoints[10][5] = 360; sweep

    _DrawPolyLineArc($aPoints, $hGraphic); draw the shape


    ; Create Double Buffer, doesn't need to be repainted on PAINT-Event
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    ;End Double Buffer add-on 2 of 3

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_Shutdown()
                Exit
            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                        "Cursor in shape: " & _PointInLineArcPoly($aPos[0], $aPos[1], $aPoints))


        EndSwitch
    WEnd
EndFunc   ;==>_Main

Func _PointInLineArcPoly($Px, $Py, $aP)
    Local $Res = 0, $j
    For $j = 1 To $aP[0][0]

        Switch $aP[$j][0]
            Case 1
                If _IsPtLeftOfLine($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4]) Then $Res += 1
            Case 2
                If _IsPtInArc($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4], $aP[$j][5]) Then $Res += 1
        EndSwitch

    Next
    Return Mod($Res, 2) = 1

EndFunc   ;==>_PointInLineArcPoly

Func _IsPtLeftOfLine($rx, $Ry, $X1, $Y1, $X2, $Y2)

    If $Ry >= Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then
        Return False
    EndIf

    Return $rx < ($Ry - $Y1) * ($X2 - $X1) / ($Y2 - $Y1) + $X1

EndFunc   ;==>IsPtLeftOfLine



Func _DrawPolyLineArc($aP, $hGr)

    For $j = 1 To $aP[0][0]
        Switch $aP[$j][0]
            Case 1
                _DrawStLine($aP, $j, $hGr)

            Case 2
                _DrawArc($aP, $j, $hGr)
        EndSwitch
    Next


EndFunc   ;==>DrawPolyLineArc

Func _DrawStLine($aK, $i, $graphic)
    _GDIPlus_GraphicsDrawLine($graphic, $aK[$i][1], $aK[$i][2], $aK[$i][3], $aK[$i][4])

EndFunc   ;==>drawStLine

Func _DrawArc($aM, $i, $graphic)

    _GDIPlus_GraphicsDrawArc($graphic, $aM[$i][1] - $aM[$i][3], $aM[$i][2] - $aM[$i][3], $aM[$i][3] * 2, $aM[$i][3] * 2, $aM[$i][4], $aM[$i][5])

EndFunc   ;==>drawArc



;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $EndAngle the start and end anglke in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to end angle counter clockwise
;Returns True if a horizontal line draw from the point to the right cuts the arc
;  once, otherwise returns false
;Author - martin
;version 2
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $sw)
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta

    ;check obvious cases
    If $xPt - $xR >= $Rad Then Return False
    If Abs($yPt - $yR) >= $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Deg2Rad
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    $Result2 = _AngleInRange($Alpha2, $StAngle, $sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt

    Return BitXOR($Result1, $Result2) = 1

EndFunc   ;==>_IsPtInArc

Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf

    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd

    While $ang < $S1
        $ang += 360
    WEnd

    While $ang > $E1
        $ang -= 360
    WEnd

    ;maybe some conditions here to decide >= or > etc
    Return $ang >= $S1 And $ang < $E1

EndFunc   ;==>_AngleInRange


;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

Func Max($a, $b)
    If $a >= $b Then Return $a
    Return $b
EndFunc   ;==>Max

Func Min($a, $b)
    If $a >= $b Then Return $b
    Return $a
EndFunc   ;==>Min

EDIT

I've added a colour parameter to my line and arc functions. When I've fixed the problem I'll post them.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I've worked out a way to decide if a point is inside when there is a combination a line types.

The problem is deciding whether to include the end points of lines or not so that you don't get duplicates.

With straight lines you can say just ignore the top point.

With arcs what is the top point of a circle? And if I ignore the top point of an arc what if it joins the top point of another arc? In that case I have ignored a point I shouldn't ignore.

So I decided that every point on the line should be considered. If the point is left of the line then give a true result but also return the points on the line that were to the right of the point we are looking at. Then add any unique points to another array $aG. Then if the number of points in the array $aG is odd it means the point is inside the shape. If the number of points is even or zero we are outside the shape.

After struggling with how to do this I think that I should have stayed with Malkey's idea. Malkey's method was to ignore the bottom point of a straight line so that a point didn't get counted twice. The same can be applied to curves if we say that if the curve moves upwards away from an end then ignore that end. This means that a curve can have 2 'bottoms' or it could have 2 'tops' or it could have a top and a bottom. Now I can't think of an example where this doesn't work so I've removed the examples I had below and I'll post them again when I've applied this better idea.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

the _AreaPoly() function which returns the area of a closed polygon,

have been included. Someone might find a use for them oneday.

Hi, i'm following this topic a little bit.

Currently i'm trying to make a GUI with area info of calculated geometry.

I rewrote the _AreaPoly() a little bit so it is of use (for me) with the GDI+ polygons.

Func _AreaPoly(ByRef $aPoints)

    Local $Med, $size
    $size = UBound($aPoints)
    Local $sPolygon[$size][2]

    $aPolygon = $aPoints

    ReDim $aPolygon[$size + 1][2]
    $aPolygon[$size][0] = $aPolygon[1][0]
    $aPolygon[$size][1] = $aPolygon[1][1]

    For $n = 1 To UBound($aPolygon) - 2
        $Med += $aPolygon[$n][0] * $aPolygon[$n + 1][1] - $aPolygon[$n + 1][0] * $aPolygon[$n][1]
    Next
    $Med /= 2
    Return $Med
EndFunc   ;==>_AreaPoly
Link to comment
Share on other sites

the _AreaPoly() function which returns the area of a closed polygon,

have been included. Someone might find a use for them oneday.

..

That's a good addition Mrtn, can you make it include arcs?

Welcome to the forums :)

Here are the examples I posted before I removed removed them because I think I have a better approach to finding a point in an arc now. It can probably be simplified but I'm fairly confident it works for all situations. (fairly)

Example 1 - an enclosed shape made of arcs and straight lines.

;using code by Malkey see http://www.autoitscript.com/forum/index....=&showtopic=89034&view=findpos
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <array.au3>
;HotKeySet("{F6}","showarray"); for debugging
Global $a1, $a2
Global $pi = 4 * ATan(1)
Global $Deg2Rad = 180 / $pi
Global $aG[20][2]

Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic

_Main()

Func showarray()
    _ArrayDisplay($aG)
EndFunc   ;==>showarray

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 380
    Local $aPoints[11][6], $aTriangle[5][2]
    Local $hButton, $MinsMaxs
    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)

    GUISetState()

    _GDIPlus_Startup()
    ;Double Buffer
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    ;End Double Buffer add-on 1 of 3

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

    ;set data in array for shape
    $aPoints[0][0] = 10; Number of  lines of Polygon
    $aPoints[1][0] = 1;st line
    $aPoints[1][1] = 10;x1
    $aPoints[1][2] = 30;y1
    $aPoints[1][3] = 10;x2
    $aPoints[1][4] = 290;y2

    $aPoints[2][0] = 2; arc
    $aPoints[2][1] = 30;center x
    $aPoints[2][2] = 290;centre y
    $aPoints[2][3] = 20;rad
    $aPoints[2][4] = 180;st angle
    $aPoints[2][5] = -90; sweep

    $aPoints[3][0] = 1;st line
    $aPoints[3][1] = 30;
    $aPoints[3][2] = 310
    $aPoints[3][3] = 190;
    $aPoints[3][4] = 310

    $aPoints[4][0] = 2; arc
    $aPoints[4][1] = 190;center x
    $aPoints[4][2] = 290;center y
    $aPoints[4][3] = 20;rad
    $aPoints[4][4] = 90;st angle
    $aPoints[4][5] = -90; sweep

    $aPoints[5][0] = 1;st line
    $aPoints[5][1] = 210;
    $aPoints[5][2] = 290
    $aPoints[5][3] = 210;
    $aPoints[5][4] = 230

    $aPoints[6][0] = 2; arc
    $aPoints[6][1] = 250;center x
    $aPoints[6][2] = 230;center y
    $aPoints[6][3] = 40;rad
    $aPoints[6][4] = 180;st angle
    $aPoints[6][5] = 90; sweep

    $aPoints[7][0] = 2; arc
    $aPoints[7][1] = 250;center x
    $aPoints[7][2] = 100;center y
    $aPoints[7][3] = 90;rad
    $aPoints[7][4] = 90;st angle
    $aPoints[7][5] = -180;sweep

    $aPoints[8][0] = 1;st line
    $aPoints[8][1] = 250;
    $aPoints[8][2] = 10
    $aPoints[8][3] = 30;
    $aPoints[8][4] = 10

    $aPoints[9][0] = 2; arc - closes shape
    $aPoints[9][1] = 30;center x
    $aPoints[9][2] = 30;center y
    $aPoints[9][3] = 20;rad
    $aPoints[9][4] = 270; st angle
    $aPoints[9][5] = -90; sweep

    $aPoints[10][0] = 2; arc - closes shape
    $aPoints[10][1] = 130;center x
    $aPoints[10][2] = 130;center y
    $aPoints[10][3] = 40;rad
    $aPoints[10][4] = 0; st angle
    $aPoints[10][5] = 360; sweep

    _DrawPolyLineArc($aPoints, $hGraphic); draw the shape


    ; Create Double Buffer, doesn't need to be repainted on PAINT-Event
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    ;End Double Buffer add-on 2 of 3
    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_Shutdown()
                Exit
            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                        "Cursor in shape: " & _PointInLineArcPoly($aPos[0], $aPos[1], $aPoints))


        EndSwitch
    WEnd
EndFunc   ;==>_Main

#region drawing functions------------------------------------------
Func _DrawPolyLineArc($aP, $hGr)

    For $j = 1 To $aP[0][0]
        Switch $aP[$j][0]
            Case 1
                _DrawStLine($aP, $j, $hGr)

            Case 2
                _DrawArc($aP, $j, $hGr)
        EndSwitch
    Next

EndFunc   ;==>_DrawPolyLineArc

Func _DrawStLine($aK, $i, $graphic)
    _GDIPlus_GraphicsDrawLine($graphic, $aK[$i][1], $aK[$i][2], $aK[$i][3], $aK[$i][4])

EndFunc   ;==>_DrawStLine

Func _DrawArc($aM, $i, $graphic)

    _GDIPlus_GraphicsDrawArc($graphic, $aM[$i][1] - $aM[$i][3], $aM[$i][2] - $aM[$i][3], $aM[$i][3] * 2, $aM[$i][3] * 2, $aM[$i][4], $aM[$i][5])

EndFunc   ;==>_DrawArc

#endregion drawing functions -----------------------------------------------------------

#region checking point functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Func _PointInLineArcPoly($Px, $Py, $aP)
    Local $Res = 0, $j

    For $j = 1 To $aP[0][0]
        ;If $j = 10 Then
        Switch $aP[$j][0]
            Case 1
                If _IsPtLeftOfLine($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4]) Then
                    $Res += 1
                EndIf
            Case 2
                If _IsPtInArc($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4], $aP[$j][5]) Then
                    $Res += 1
                EndIf
        EndSwitch
        ;EndIf
    Next

    Return Mod($Res, 2) = 1

EndFunc   ;==>_PointInLineArcPoly


Func _IsPtLeftOfLine($Rx, $Ry, $X1, $Y1, $X2, $Y2)
    If $Ry >= Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then
        Return False
    EndIf


    Return $Rx < ($Ry - $Y1) * ($X2 - $X1) / ($Y2 - $Y1) + $X1

EndFunc   ;==>_IsPtLeftOfLine


;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $EndAngle the start and end anglke in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to start angle plus sweep
;Returns True if a horizontal line draw from the point to the right cuts the arc
;       once. If the horizontal line hits an end of the arc then it returns true only if that end is a top. A top end means
;       the arc moves down away from that end.
;       If the horizontal line is a tangent to the arc then it returns false.
;Author - martin
;version 3
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw)
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta, $j


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Deg2Rad
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 and _OneIsSameAngle($StAngle,$StAngle + $sw,270) Then
        $result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)

    Return BitXOR($Result1, $Result2) = 1

EndFunc   ;==>_IsPtInArc

func _OneIsSameANgle($A,$B,$C)
    _SetAngle($A)
    _SetAngle($B)

   Return BitXOR( ($A = $C), ($B = $C))

EndFunc

;=== SetAngle ==========
;converts the angle to be in range 0 to 360
func _SetAngle(ByRef $aS)
    while $aS < 0
        $aS += 360
    WEnd

    while $aS > 360
        $aS -= 360
    WEnd
EndFunc


Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    Local $aa, $bb

    If $sweepA >= 360 Then Return True

    $aa = $startA
    _SetAngle($aa)

    $bb = $startA + $sweepA
    _SetAngle($bb)


    If $ang = $aa Then;check if start a top or bottom type of end
        If $sweepA > 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA < 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf

    If $ang = $bb Then; is end a top or bottom type
        If $sweepA < 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA > 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf



    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf

    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd

    While $ang < $S1
        $ang += 360
    WEnd

    While $ang > $E1
        $ang -= 360
    WEnd


    Return $ang >= $S1 And $ang <= $E1

EndFunc   ;==>_AngleInRange
#endregion checking point functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

Func Max($a, $b)
    If $a >= $b Then Return $a
    Return $b
EndFunc   ;==>Max

Func Min($a, $b)
    If $a >= $b Then Return $b
    Return $a
EndFunc   ;==>Min

Example 2, a pie chart with a tooltip which depends on which section the cursor is over.

;using code by Malkey see http://www.autoitscript.com/forum/index....=&showtopic=89034&view=findpos
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <array.au3>

Global $a1, $a2
Global $pi = 4 * ATan(1)
Global $Deg2Rad = 180 / $pi

Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic

_Main()

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 380
    Local $aPts, $aTriangle[5][2]
    Local $hButton, $ShapeCount, $ANgleSum
    Local $sText[8] = ["place the cursor over the pie chart", "people who don't understand pie charts", "thank you William Playfair " & @CRLF & " and Florence Nightingale", "people who have no running water", "People who can't ride a bicycle", _
            "people who have blond hair", "people who don't own shoes", "people who never work"]
    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)

    GUISetState()

    _GDIPlus_Startup()
    ;Double Buffer
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    ;End Double Buffer add-on 1 of 3

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

    ;set data in array for shape
    Dim $Segments[7] = [20, 80, 50, 70, 10, 40, 90]
    Global $AllShapes[UBound($Segments)]

    $ANgleSum = 0
    For $ShapeCount = 0 To UBound($Segments) - 1
        $AllShapes[$ShapeCount] = _PieShape(150, 150, 100, $ANgleSum, $Segments[$ShapeCount], $hGraphic)
        _DrawPolyLineArc($AllShapes[$ShapeCount], $hGraphic); draw the shape
        $ANgleSum += $Segments[$ShapeCount]
        ;_GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
        ;sleep(3000)
    Next

    ; Create Double Buffer, doesn't need to be repainted on PAINT-Event
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    ;End Double Buffer add-on 2 of 3

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_Shutdown()
                Exit
            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                ;ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                ;       "Cursor in segment: " & _PointInPie($aPos[0], $aPos[1], $AllShapes))
                ToolTip($sText[_PointInPie($aPos[0], $aPos[1], $AllShapes)])

        EndSwitch
    WEnd
EndFunc   ;==>_Main

Func _PointInPie($x, $y, $aP)
    Local $n
    For $n = 0 To UBound($aP) - 1
        If _PointInLineArcPoly($x, $y, $aP[$n]) Then Return $n + 1
    Next

EndFunc   ;==>_PointInPie


Func _PieShape($Rx, $Ry, $Rad, $StartAng, $Sweep, $hG)
    Local $aPoints[4][6]
    Local $hBr = _GDIPlus_BrushCreateSolid(0xff000000 + Random(20, 200, 1) * 2 ^ 16 + Random(20, 200, 1) * 2 ^ 8 + Random(20, 200, 1))

    _GDIPlus_GraphicsFillPie($hG, $Rx - $Rad, $Ry - $Rad, $Rad * 2, $Rad * 2, $StartAng, $Sweep, $hBr)
    _GDIPlus_BrushDispose($hBr)


    $aPoints[0][0] = 3;3 lines
    $aPoints[1][0] = 2;line is an arc
    $aPoints[1][1] = $Rx;center x
    $aPoints[1][2] = $Ry;centre y
    $aPoints[1][3] = $Rad;rad
    $aPoints[1][4] = $StartAng;st angle
    $aPoints[1][5] = $Sweep; sweep

    $aPoints[2][0] = 1;st line
    $aPoints[2][1] = $Rx;
    $aPoints[2][2] = $Ry
    $aPoints[2][3] = $Rx + $Rad * Cos($StartAng / $Deg2Rad);
    $aPoints[2][4] = $Ry + $Rad * Sin($StartAng / $Deg2Rad);

    $aPoints[3][0] = 1;st line
    $aPoints[3][1] = $Rx;
    $aPoints[3][2] = $Ry
    $aPoints[3][3] = $Rx + $Rad * Cos(($StartAng + $Sweep) / $Deg2Rad);
    $aPoints[3][4] = $Ry + $Rad * Sin(($StartAng + $Sweep) / $Deg2Rad);

    Return $aPoints





EndFunc   ;==>_PieShape

#region drawing functions
Func _DrawPolyLineArc($aP, $hGr)

    For $j = 1 To $aP[0][0]
        Switch $aP[$j][0]
            Case 1
                _DrawStLine($aP, $j, $hGr)

            Case 2
                _DrawArc($aP, $j, $hGr)
        EndSwitch
    Next

EndFunc   ;==>_DrawPolyLineArc

Func _DrawStLine($aK, $i, $graphic)
    _GDIPlus_GraphicsDrawLine($graphic, $aK[$i][1], $aK[$i][2], $aK[$i][3], $aK[$i][4])

EndFunc   ;==>_DrawStLine

Func _DrawArc($aM, $i, $graphic)

    _GDIPlus_GraphicsDrawArc($graphic, $aM[$i][1] - $aM[$i][3], $aM[$i][2] - $aM[$i][3], $aM[$i][3] * 2, $aM[$i][3] * 2, $aM[$i][4], $aM[$i][5])

EndFunc   ;==>_DrawArc

#endregion drawing functions

#region checking point functions
Func _PointInLineArcPoly($Px, $Py, $aP)
    Local $Res = 0, $j

    For $j = 1 To $aP[0][0]
        ;If $j = 10 Then
        Switch $aP[$j][0]
            Case 1
                If _IsPtLeftOfLine($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4]) Then
                    $Res += 1
                EndIf
            Case 2
                If _IsPtInArc($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4], $aP[$j][5]) Then
                    $Res += 1
                EndIf
        EndSwitch
        ;EndIf
    Next

    Return Mod($Res, 2) = 1

EndFunc   ;==>_PointInLineArcPoly


Func _IsPtLeftOfLine($Rx, $Ry, $X1, $Y1, $X2, $Y2)
    If $Ry >= Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then
        Return False
    EndIf


    Return $Rx < ($Ry - $Y1) * ($X2 - $X1) / ($Y2 - $Y1) + $X1

EndFunc   ;==>_IsPtLeftOfLine


;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $EndAngle the start and end anglke in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to start angle plus sweep
;Returns True if a horizontal line draw from the point to the right cuts the arc
;       once. If the horizontal line hits an end of the arc then it returns true only if that end is a top. A top end means
;       the arc moves down away from that end.
;       If the horizontal line is a tangent to the arc then it returns false.
;Author - martin
;version 3
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw)
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta, $j


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Deg2Rad
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 and _OneIsSameAngle($StAngle,$StAngle + $sw,270) Then
        $result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)

    Return BitXOR($Result1, $Result2) = 1

EndFunc   ;==>_IsPtInArc

func _OneIsSameANgle($A,$B,$C)
    _SetAngle($A)
    _SetAngle($B)

    if $A = $C or $B = $C then return True

    return False
EndFunc

;=== SetAngle ==========
;converts the angle to be in range 0 to 360
func _SetAngle(ByRef $aS)
    while $aS < 0
        $aS += 360
    WEnd

    while $aS > 360
        $aS -= 360
    WEnd
EndFunc



Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    Local $aa, $bb

    If $sweepA >= 360 Then Return True

    $aa = $startA
    _SetAngle($aa)

    $bb = $startA + $sweepA
    _SetAngle($bb)


    If $ang = $aa Then;check if start a top or bottom type of end
        If $sweepA > 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA < 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf

    If $ang = $bb Then; is end a top or bottom type
        If $sweepA < 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA > 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf



    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf

    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd

    While $ang < $S1
        $ang += 360
    WEnd

    While $ang > $E1
        $ang -= 360
    WEnd


    Return $ang >= $S1 And $ang <= $E1

EndFunc   ;==>_AngleInRange
#endregion checking point functions


;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

Func Max($a, $b)
    If $a >= $b Then Return $a
    Return $b
EndFunc   ;==>Max

Func Min($a, $b)
    If $a >= $b Then Return $b
    Return $a
EndFunc   ;==>Min

EDIT: Correct error in _SetAngle function. (-= was +=), and changed _OneIsSame to return BitXOR rather than Or.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Now I can calculate the path for my routing tool :)

;using code by Malkey see http://www.autoitscript.com/forum/index....=&showtopic=89034&view=findpos
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <array.au3>
;HotKeySet("{F6}","showarray"); for debugging
Global $a1, $a2
Global $pi = 4 * ATan(1)
Global $Rad2Deg = 180 / $pi
Global $aG[20][2]

Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic

_Main()

Func showarray()
    _ArrayDisplay($aG)
EndFunc   ;==>showarray

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 380
    Local $aPoints[11][6], $aTriangle[5][2]
    Local $hButton1, $hButton2, $MinsMaxs,$dx,$dy, $beta
    Local $marg = 8
    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY + 50)
    $hButton1 = GUICtrlCreateButton("Create Inside Path", 80, 400)
    $hButton2 = GUICtrlCreateButton("Create Outside Path", 200, 400)
    GUISetState()

    _GDIPlus_Startup()
    ;Double Buffer
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)

    ;End Double Buffer add-on 1 of 3

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

    ;set data in array for shape
    $aPoints[0][0] = 10; Number of  lines of Polygon
;calculate bits for the end start angle of left hand corners and the positions of the end of the left-hand straight edge
    $beta = atan(40/260)
    $dx = 20 * cos($beta)
    $dy = 20 * sin($beta)
ConsoleWrite($beta*$Rad2Deg & @CRLF)
    $aPoints[1][0] = 1;st line
    $aPoints[1][1] = 70 - $dx;x1
    $aPoints[1][2] = 30 - $dy;y1
    $aPoints[1][3] = 30 - $dx;x2
    $aPoints[1][4] = 290 - $dy;y2

    $aPoints[2][0] = 2; arc
    $aPoints[2][1] = 30;center x
    $aPoints[2][2] = 290;centre y
    $aPoints[2][3] = 20;rad
    $aPoints[2][4] = 90;st angle
    $aPoints[2][5] = 90+$beta*$Rad2Deg; sweep

    $aPoints[3][0] = 1;st line
    $aPoints[3][1] = 30;
    $aPoints[3][2] = 310
    $aPoints[3][3] = 190;
    $aPoints[3][4] = 310

    $aPoints[4][0] = 2; arc
    $aPoints[4][1] = 190;center x
    $aPoints[4][2] = 290;center y
    $aPoints[4][3] = 20;rad
    $aPoints[4][4] = 90;st angle
    $aPoints[4][5] = -90; sweep

    $aPoints[5][0] = 1;st line
    $aPoints[5][1] = 210;
    $aPoints[5][2] = 290
    $aPoints[5][3] = 210;
    $aPoints[5][4] = 230

    $aPoints[6][0] = 2; arc
    $aPoints[6][1] = 250;center x
    $aPoints[6][2] = 230;center y
    $aPoints[6][3] = 40;rad
    $aPoints[6][4] = 180;st angle
    $aPoints[6][5] = 90; sweep

    $aPoints[7][0] = 2; arc
    $aPoints[7][1] = 250;center x
    $aPoints[7][2] = 100;center y
    $aPoints[7][3] = 90;rad
    $aPoints[7][4] = 90;st angle
    $aPoints[7][5] = -180;sweep

    $aPoints[8][0] = 1;st line
    $aPoints[8][1] = 250;
    $aPoints[8][2] = 10
    $aPoints[8][3] = 70;
    $aPoints[8][4] = 10

    $aPoints[9][0] = 2; arc - closes shape
    $aPoints[9][1] = 70;center x
    $aPoints[9][2] = 30;center y
    $aPoints[9][3] = 20;rad
    $aPoints[9][4] = 270; st angle
    $aPoints[9][5] = -90 + $beta*$Rad2Deg; sweep

    $aPoints[10][0] = 2; arc -
    $aPoints[10][1] = 300;center x
    $aPoints[10][2] = 260;center y
    $aPoints[10][3] = 60;rad
    $aPoints[10][4] = 270; st angle
    $aPoints[10][5] = 360; sweep

    _DrawPolyLineArc($aPoints, $hGraphic); draw the shape


    ; Create Double Buffer, doesn't need to be repainted on PAINT-Event
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    ;End Double Buffer add-on 2 of 3
    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_Shutdown()
                Exit
            Case $hButton1
                _DrawPolyLineArc(_CreateInnerOuterCopy($aPoints, $hGraphic, $marg), $hGraphic, 0xff0000)
                _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
            Case $hButton2
                _DrawPolyLineArc(_CreateInnerOuterCopy($aPoints, $hGraphic, -$marg), $hGraphic, 0x00ff00)
                _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                        "Cursor in shape: " & _PointInLineArcPoly($aPos[0], $aPos[1], $aPoints))


        EndSwitch
    WEnd
EndFunc   ;==>_Main

;======= _CreateInsideCopy ===================
;version 2
;Version 1 assumes arcs start and end at 90 degree multiples and straight lines are vertical or horizontal.
;Version 2 allows for lines at any angle but assumes lines join arcs at a tangent.
;assumes the margin is less than the radius of the smallest arc
;so very limited.
;returns an array of the new shape
;if margin is > 0 then inner copy
;if $margin < 0 then outer copy
Func _CreateInnerOuterCopy($aPts, $hGr, $margin)
    Local $aPoints[UBound($aPts, 1)][6], $n, $posx, $posy, $use, $alpha, $x1, $y1
    $aPoints[0][0] = $aPts[0][0]
    For $n = 1 To UBound($aPts) - 1
        Switch $aPts[$n][0] ;line type
            Case 1;straight line
                $aPoints[$n][0] = 1
                ConsoleWrite($aPts[$n][1] & ', ' & $aPts[$n][2] & ', ' & $aPts[$n][3] & ', ' & $aPts[$n][4] & ', ' & @CRLF)

                ;get a point at the end of a paralle line $margin away
                If $aPts[$n][1] = $aPts[$n][3] Then;vertical line
                    ConsoleWrite("vertical" & @CRLF)
                    $alpha = $pi / 2
                Else
                    $alpha = ATan(($aPts[$n][4] - $aPts[$n][2]) / ($aPts[$n][3] - $aPts[$n][1]))
                EndIf

                $x1 = $aPts[$n][1] + $margin * Sin($alpha)
                $y1 = $aPts[$n][2] - $margin * Cos($alpha)
                If BitXOR(_PointInLineArcPoly($x1, $y1, $aPts), $margin < 0) Then
                    $aPoints[$n][1] = $x1
                    $aPoints[$n][2] = $y1
                    $aPoints[$n][3] = $aPts[$n][3] + $margin * Sin($alpha)
                    $aPoints[$n][4] = $aPts[$n][4] - $margin * Cos($alpha)
                Else
                    $aPoints[$n][1] = $aPts[$n][1] - $margin * Sin($alpha)
                    $aPoints[$n][2] = $aPts[$n][2] + $margin * Cos($alpha)
                    $aPoints[$n][3] = $aPts[$n][3] - $margin * Sin($alpha)
                    $aPoints[$n][4] = $aPts[$n][4] + $margin * Cos($alpha)
                EndIf


            Case 2 ; arc
                $aPoints[$n][0] = 2
                $aPoints[$n][1] = $aPts[$n][1]
                $aPoints[$n][2] = $aPts[$n][2]
                $aPoints[$n][4] = $aPts[$n][4]
                $aPoints[$n][5] = $aPts[$n][5]
                $posx = $aPts[$n][1] + ($aPts[$n][3] - $margin) * Cos($aPts[$n][4] / $Rad2Deg)
                $posy = $aPts[$n][2] + ($aPts[$n][3] - $margin) * Sin($aPts[$n][4] / $Rad2Deg)
                ConsoleWrite("posx, posy = " & $posx & ', ' & $posy & @CRLF)
                If BitXOR(_PointInLineArcPoly($posx, $posy, $aPts), $margin < 0) Then
                    ConsoleWrite("is inside" & @CRLF)
                    $aPoints[$n][3] = $aPts[$n][3] - $margin
                Else
                    $aPoints[$n][3] = $aPts[$n][3] + $margin
                EndIf


        EndSwitch

    Next
    ;_ArrayDisplay($aPoints)
    Return $aPoints

EndFunc   ;==>_CreateInnerOuterCopy


;=========== _GetParallelStLines ======================
;returns an array containing the end points for 2 parallel lines to $x1, $y1 to $x2, $y2
; the lines are either side of the given line displaced by a distance $gap measured at right angles to the line.
Func _GetParallelStLine($x1, $y1, $x2, $y2, $gap)
    Local $slope, $alpha, $Beta, $n
    Dim $Res[4]

    ;get angle of line in radians
    $alpha = ATan(($y2 - $y1) / ($x2 - $x1))

    $Res[0] = $x1 + $gap * Cos($alpha)
    $Res[2] = $x2 + $gap * Cos($alpha)
    $Res[1] = $x1 + $gap * Sin($alpha)
    $Res[3] = $x2 + $gap * Sin($alpha)



EndFunc   ;==>_GetParallelStLine



#region drawing functions
Func _DrawPolyLineArc($aP, $hGr, $colour = 0)
Local $hPen = _GDIPlus_PenCreate(0xff000000 + $colour)
    For $j = 1 To $aP[0][0]
        Switch $aP[$j][0]
            Case 1
                _DrawStLine($aP, $j, $hGr, $hPen)

            Case 2
                _DrawArc($aP, $j, $hGr, $hPen)
        EndSwitch
    Next
_GDIPlus_PenDispose($hPen)
EndFunc   ;==>_DrawPolyLineArc

Func _DrawStLine($aK, $i, $graphic, $hPen = 0)
    _GDIPlus_GraphicsDrawLine($graphic, $aK[$i][1], $aK[$i][2], $aK[$i][3], $aK[$i][4], $hPen)

EndFunc   ;==>_DrawStLine

Func _DrawArc($aM, $i, $graphic, $hPen = 0)

    _GDIPlus_GraphicsDrawArc($graphic, $aM[$i][1] - $aM[$i][3], $aM[$i][2] - $aM[$i][3], $aM[$i][3] * 2, $aM[$i][3] * 2, $aM[$i][4], $aM[$i][5], $hPen)

EndFunc   ;==>_DrawArc

#endregion drawing functions

#region checking point functions
Func _PointInLineArcPoly($Px, $Py, $aP)
    Local $Res = 0, $j

    For $j = 1 To $aP[0][0]
        ;If $j = 10 Then
        Switch $aP[$j][0]
            Case 1
                If _IsPtLeftOfLine($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4]) Then
                    $Res += 1
                EndIf
            Case 2
                If _IsPtInArc($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4], $aP[$j][5]) Then
                    $Res += 1
                EndIf
        EndSwitch
        ;EndIf
    Next

    Return Mod($Res, 2) = 1

EndFunc   ;==>_PointInLineArcPoly


Func _IsPtLeftOfLine($Rx, $Ry, $x1, $y1, $x2, $y2)
    If $Ry >= Max($y1, $y2) Or $Ry < Min($y1, $y2) Then
        Return False
    EndIf


    Return $Rx < ($Ry - $y1) * ($x2 - $x1) / ($y2 - $y1) + $x1

EndFunc   ;==>_IsPtLeftOfLine


;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $EndAngle the start and end anglke in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to start angle plus sweep
;Returns True if a horizontal line draw from the point to the right cuts the arc
;       once. If the horizontal line hits an end of the arc then it returns true only if that end is a top. A top end means
;       the arc moves down away from that end.
;       If the horizontal line is a tangent to the arc then it returns false.
;Author - martin
;version 3
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw)
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $Beta, $j


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $Beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $Beta * $Rad2Deg
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($Beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 And _OneIsSameAngle($StAngle, $StAngle + $Sw, 270) Then
        $Result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($Beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)

    Return BitXOR($Result1, $Result2) = 1

EndFunc   ;==>_IsPtInArc

Func _OneIsSameANgle($A, $B, $C)
    _SetAngle($A)
    _SetAngle($B)

    Return BitXOR(($A = $C), ($B = $C))

EndFunc   ;==>_OneIsSameANgle

;=== SetAngle ==========
;converts the angle to be in range 0 to 360
Func _SetAngle(ByRef $aS)
    While $aS < 0
        $aS += 360
    WEnd

    While $aS > 360
        $aS -= 360
    WEnd
EndFunc   ;==>_SetAngle



Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    Local $aa, $bb

    If $sweepA >= 360 Then Return True

    $aa = $startA
    _SetAngle($aa)

    $bb = $startA + $sweepA
    _SetAngle($bb)


    If $ang = $aa Then;check if start a top or bottom type of end
        If $sweepA > 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA < 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf

    If $ang = $bb Then; is end a top or bottom type
        If $sweepA < 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA > 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf



    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf

    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd

    While $ang < $S1
        $ang += 360
    WEnd

    While $ang > $E1
        $ang -= 360
    WEnd


    Return $ang >= $S1 And $ang <= $E1

EndFunc   ;==>_AngleInRange
#endregion checking point functions

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME, $RDW_ALLCHILDREN));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

Func Max($A, $B)
    If $A >= $B Then Return $A
    Return $B
EndFunc   ;==>Max

Func Min($A, $B)
    If $A >= $B Then Return $B
    Return $A
EndFunc   ;==>Min

I couldn't resist showing this effect

;using code by Malkey see http://www.autoitscript.com/forum/index....=&showtopic=89034&view=findpos
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <array.au3>
;HotKeySet("{F6}","showarray"); for debugging
Global $a1, $a2
Global $pi = 4 * ATan(1)
Global $Rad2Deg = 180 / $pi
Global $aG[20][2]

Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic

_Main()

Func showarray()
    _ArrayDisplay($aG)
EndFunc   ;==>showarray

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 430
    Local $aPoints[11][6], $aTriangle[5][2]
    Local $hButton1, $hButton2, $ed, $MinsMaxs, $dx, $dy, $beta, $col
    Local $marg = 8, $InOrOut = 1
    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)
    $hButton1 = GUICtrlCreateButton("Convert to Pipes", 80, 400)
    ; $hButton2 = GUICtrlCreateButton("Create Outside Path", 200, 400)
    ;$ed = GUICtrlCreateinput("",130,360)


    GUISetState()

    _GDIPlus_Startup()
    ;Double Buffer
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY - 70, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic,2)
    ;End Double Buffer add-on 1 of 3

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

    ;set data in array for shape
    $aPoints[0][0] = 10; Number of  lines of Polygon
    ;calculate bits for the end start angle of left hand corners and the positions of the end of the left-hand straight edge
    $beta = ATan(40 / 260)
    $dx = 20 * Cos($beta)
    $dy = 20 * Sin($beta)
    ConsoleWrite($beta * $Rad2Deg & @CRLF)
    $aPoints[1][0] = 1;st line
    $aPoints[1][1] = 70 - $dx;x1
    $aPoints[1][2] = 30 - $dy;y1
    $aPoints[1][3] = 30 - $dx;x2
    $aPoints[1][4] = 290 - $dy;y2

    $aPoints[2][0] = 2; arc
    $aPoints[2][1] = 30;center x
    $aPoints[2][2] = 290;centre y
    $aPoints[2][3] = 20;rad
    $aPoints[2][4] = 90;st angle
    $aPoints[2][5] = 90 + $beta * $Rad2Deg; sweep

    $aPoints[3][0] = 1;st line
    $aPoints[3][1] = 30;
    $aPoints[3][2] = 310
    $aPoints[3][3] = 191;
    $aPoints[3][4] = 310

    $aPoints[4][0] = 2; arc
    $aPoints[4][1] = 190;center x
    $aPoints[4][2] = 290;center y
    $aPoints[4][3] = 20;rad
    $aPoints[4][4] = 90;st angle
    $aPoints[4][5] = -90; sweep

    $aPoints[5][0] = 1;st line
    $aPoints[5][1] = 210;
    $aPoints[5][2] = 291
    $aPoints[5][3] = 210;
    $aPoints[5][4] = 230

    $aPoints[6][0] = 2; arc
    $aPoints[6][1] = 250;center x
    $aPoints[6][2] = 230;center y
    $aPoints[6][3] = 40;rad
    $aPoints[6][4] = 180;st angle
    $aPoints[6][5] = 90; sweep

    $aPoints[7][0] = 2; arc
    $aPoints[7][1] = 250;center x
    $aPoints[7][2] = 100;center y
    $aPoints[7][3] = 90;rad
    $aPoints[7][4] = 90;st angle
    $aPoints[7][5] = -180;sweep

    $aPoints[8][0] = 1;st line
    $aPoints[8][1] = 251;
    $aPoints[8][2] = 10
    $aPoints[8][3] = 70;
    $aPoints[8][4] = 10

    $aPoints[9][0] = 2; arc - closes shape
    $aPoints[9][1] = 70;center x
    $aPoints[9][2] = 30;center y
    $aPoints[9][3] = 20;rad
    $aPoints[9][4] = 270; st angle
    $aPoints[9][5] = -90 + $beta * $Rad2Deg; sweep

    $aPoints[10][0] = 2; arc -
    $aPoints[10][1] = 330;center x
    $aPoints[10][2] = 290;center y
    $aPoints[10][3] = 60;rad
    $aPoints[10][4] = 270; st angle
    $aPoints[10][5] = 360; sweep

    _DrawPolyLineArc($aPoints, $hGraphic); draw the shape


    ; Create Double Buffer, doesn't need to be repainted on PAINT-Event
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    ;End Double Buffer add-on 2 of 3
    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_Shutdown()
                Exit
            Case $hButton1

                For $marg = 0 To 20
                    $col = 5* (20-$marg) + 4 * (20-$marg) * 2 ^ 8 +  3* (20-$marg) * 2 ^ 16 + 0x774422

                    _DrawPolyLineArc(_CreateInnerOuterCopy($aPoints, $hGraphic, $marg * $InOrOut), $hGraphic, $col, 2)
                    _DrawPolyLineArc(_CreateInnerOuterCopy($aPoints, $hGraphic, -$marg * $InOrOut), $hGraphic, $col, 2)
                    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
                Next

            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                If $aPos[1] < 360 Then
                    ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                            "Cursor in shape: " & _PointInLineArcPoly($aPos[0], $aPos[1], $aPoints))
                Else
                    ToolTip("")
                EndIf



        EndSwitch
    WEnd
EndFunc   ;==>_Main

;======= _CreateInsideCopy ===================
;version 2
;Version 1 assumes arcs start and end at 90 degree multiples and straight lines are vertical or horizontal.
;Version 2 allows for lines at any angle but assumes lines join arcs at a tangent.
;assumes the margin is less than the radius of the smallest arc
;so very limited.
;returns an array of the new shape
;if margin is > 0 then inner copy
;if $margin < 0 then outer copy
Func _CreateInnerOuterCopy($aPts, $hGr, $margin)
    Local $aPoints[UBound($aPts, 1)][6], $n, $posx, $posy, $use, $alpha, $x1, $y1
    $aPoints[0][0] = $aPts[0][0]
    For $n = 1 To UBound($aPts) - 1
        Switch $aPts[$n][0] ;line type
            Case 1;straight line
                $aPoints[$n][0] = 1
                ConsoleWrite($aPts[$n][1] & ', ' & $aPts[$n][2] & ', ' & $aPts[$n][3] & ', ' & $aPts[$n][4] & ', ' & @CRLF)

                ;get a point at the end of a paralle line $margin away
                If $aPts[$n][1] = $aPts[$n][3] Then;vertical line
                    ConsoleWrite("vertical" & @CRLF)
                    $alpha = $pi / 2
                Else
                    $alpha = ATan(($aPts[$n][4] - $aPts[$n][2]) / ($aPts[$n][3] - $aPts[$n][1]))
                EndIf

                $x1 = $aPts[$n][1] + $margin * Sin($alpha)
                $y1 = $aPts[$n][2] - $margin * Cos($alpha)
                If BitXOR(_PointInLineArcPoly($x1, $y1, $aPts), $margin < 0) Then
                    $aPoints[$n][1] = $x1
                    $aPoints[$n][2] = $y1
                    $aPoints[$n][3] = $aPts[$n][3] + $margin * Sin($alpha)
                    $aPoints[$n][4] = $aPts[$n][4] - $margin * Cos($alpha)
                Else
                    $aPoints[$n][1] = $aPts[$n][1] - $margin * Sin($alpha)
                    $aPoints[$n][2] = $aPts[$n][2] + $margin * Cos($alpha)
                    $aPoints[$n][3] = $aPts[$n][3] - $margin * Sin($alpha)
                    $aPoints[$n][4] = $aPts[$n][4] + $margin * Cos($alpha)
                EndIf


            Case 2 ; arc
                $aPoints[$n][0] = 2
                $aPoints[$n][1] = $aPts[$n][1]
                $aPoints[$n][2] = $aPts[$n][2]
                $aPoints[$n][4] = $aPts[$n][4]
                $aPoints[$n][5] = $aPts[$n][5]
                $posx = $aPts[$n][1] + ($aPts[$n][3] - $margin) * Cos($aPts[$n][4] / $Rad2Deg)
                $posy = $aPts[$n][2] + ($aPts[$n][3] - $margin) * Sin($aPts[$n][4] / $Rad2Deg)
                ConsoleWrite("posx, posy = " & $posx & ', ' & $posy & @CRLF)
                If BitXOR(_PointInLineArcPoly($posx, $posy, $aPts), $margin < 0) Then
                    ConsoleWrite("is inside" & @CRLF)
                    $aPoints[$n][3] = $aPts[$n][3] - $margin
                Else
                    $aPoints[$n][3] = $aPts[$n][3] + $margin
                EndIf


        EndSwitch

    Next
    ;_ArrayDisplay($aPoints)
    Return $aPoints

EndFunc   ;==>_CreateInnerOuterCopy


;=========== _GetParallelStLines ======================
;returns an array containing the end points for 2 parallel lines to $x1, $y1 to $x2, $y2
; the lines are either side of the given line displaced by a distance $gap measured at right angles to the line.
Func _GetParallelStLine($x1, $y1, $x2, $y2, $gap)
    Local $slope, $alpha, $beta, $n
    Dim $Res[4]

    ;get angle of line in radians
    $alpha = ATan(($y2 - $y1) / ($x2 - $x1))

    $Res[0] = $x1 + $gap * Cos($alpha)
    $Res[2] = $x2 + $gap * Cos($alpha)
    $Res[1] = $x1 + $gap * Sin($alpha)
    $Res[3] = $x2 + $gap * Sin($alpha)



EndFunc   ;==>_GetParallelStLine



#region drawing functions
Func _DrawPolyLineArc($aP, $hGr, $colour = 0, $lineWid = 1)
    Local $hPen = _GDIPlus_PenCreate(0xff000000 + $colour, $lineWid)
    For $j = 1 To $aP[0][0]
        Switch $aP[$j][0]
            Case 1
                _DrawStLine($aP, $j, $hGr, $hPen)

            Case 2
                _DrawArc($aP, $j, $hGr, $hPen)
        EndSwitch
    Next
    _GDIPlus_PenDispose($hPen)
EndFunc   ;==>_DrawPolyLineArc

Func _DrawStLine($aK, $i, $graphic, $hPen = 0)
    _GDIPlus_GraphicsDrawLine($graphic, $aK[$i][1], $aK[$i][2], $aK[$i][3], $aK[$i][4], $hPen)

EndFunc   ;==>_DrawStLine

Func _DrawArc($aM, $i, $graphic, $hPen = 0)

    _GDIPlus_GraphicsDrawArc($graphic, $aM[$i][1] - $aM[$i][3], $aM[$i][2] - $aM[$i][3], $aM[$i][3] * 2, $aM[$i][3] * 2, $aM[$i][4], $aM[$i][5], $hPen)

EndFunc   ;==>_DrawArc

#endregion drawing functions

#region checking point functions
Func _PointInLineArcPoly($Px, $Py, $aP)
    Local $Res = 0, $j

    For $j = 1 To $aP[0][0]
        ;If $j = 10 Then
        Switch $aP[$j][0]
            Case 1
                If _IsPtLeftOfLine($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4]) Then
                    $Res += 1
                EndIf
            Case 2
                If _IsPtInArc($Px, $Py, $aP[$j][1], $aP[$j][2], $aP[$j][3], $aP[$j][4], $aP[$j][5]) Then
                    $Res += 1
                EndIf
        EndSwitch
        ;EndIf
    Next

    Return Mod($Res, 2) = 1

EndFunc   ;==>_PointInLineArcPoly


Func _IsPtLeftOfLine($Rx, $Ry, $x1, $y1, $x2, $y2)
    If $Ry >= Max($y1, $y2) Or $Ry < Min($y1, $y2) Then
        Return False
    EndIf


    Return $Rx < ($Ry - $y1) * ($x2 - $x1) / ($y2 - $y1) + $x1

EndFunc   ;==>_IsPtLeftOfLine


;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $EndAngle the start and end anglke in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to start angle plus sweep
;Returns True if a horizontal line draw from the point to the right cuts the arc
;       once. If the horizontal line hits an end of the arc then it returns true only if that end is a top. A top end means
;       the arc moves down away from that end.
;       If the horizontal line is a tangent to the arc then it returns false.
;Author - martin
;version 3
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw)
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta, $j


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Rad2Deg
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 And _OneIsSameAngle($StAngle, $StAngle + $Sw, 270) Then
        $Result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)

    Return BitXOR($Result1, $Result2) = 1

EndFunc   ;==>_IsPtInArc

Func _OneIsSameANgle($A, $B, $C)
    _SetAngle($A)
    _SetAngle($B)

    Return BitXOR(($A = $C), ($B = $C))

EndFunc   ;==>_OneIsSameANgle

;=== SetAngle ==========
;converts the angle to be in range 0 to 360
Func _SetAngle(ByRef $aS)
    While $aS < 0
        $aS += 360
    WEnd

    While $aS > 360
        $aS -= 360
    WEnd
EndFunc   ;==>_SetAngle



Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    Local $aa, $bb

    If $sweepA >= 360 Then Return True

    $aa = $startA
    _SetAngle($aa)

    $bb = $startA + $sweepA
    _SetAngle($bb)


    If $ang = $aa Then;check if start a top or bottom type of end
        If $sweepA > 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA < 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf

    If $ang = $bb Then; is end a top or bottom type
        If $sweepA < 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA > 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf

    EndIf



    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf

    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd

    While $ang < $S1
        $ang += 360
    WEnd

    While $ang > $E1
        $ang -= 360
    WEnd


    Return $ang >= $S1 And $ang <= $E1

EndFunc   ;==>_AngleInRange
#endregion checking point functions

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME, $RDW_ALLCHILDREN));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

Func Max($A, $B)
    If $A >= $B Then Return $A
    Return $B
EndFunc   ;==>Max

Func Min($A, $B)
    If $A >= $B Then Return $B
    Return $A
EndFunc   ;==>Min

EDIT 26th March 2011 - Added colour parameter to line drawing functions.

Added ability of _CreateInnerOuterCopy to deal with straight lines at any angle provided they join arcs at a tangent.

Added an example of converting lines in a shape to pipes.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Mrtn

The good news is your _AreaPoly() function returns the same result as the _AreaPoly() function in the first post #1, this thread.

And again, welcome to the forums.

Martin

Using your example for the routing tool path, post #25, I used this

Case $hButton1
                For $i = 5 To 120 Step 5
                    _DrawPolyLineArc(_CreateInnerOuterCopy($aPoints, $hGraphic, $i), $hGraphic)
                    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
                Next

The objective being to route the entire area within the shape.

I am not certain what the parameter "$Sw" in IsPtInArc() stands for, $EndAngle or $fSweepAngle?

[A thought]

Just as "$Rx, $Ry" replaces "$hGraphics" in

_GDIPlus_GraphicsDrawLine($hGraphics, $iX1, $iY1, $iX2, $iY2[, $hPen = 0])

to get the

_IsPtLeftOfLine($Rx, $Ry, $iX1, $iY1, $iX2, $iY2)

function, I thought from

_GDIPlus_GraphicsDrawArc($hGraphics, $iX, $iY, $iWidth, $iHeight, $fStartAngle, $fSweepAngle[, $hPen = 0])

the function

_IsPtInArc($Rx, $Ry, $iX, $iY, $iWidth, $iHeight, $fStartAngle, $fSweepAngle)

would be a logical step - having matching parameters.

Or more correctly, it should be called _IsPtLeftOfArc().

[Theory]

If a specific shape is made-up of a number of connecting lines and arcs, then, with the same number of appropiate _IsPtLeftOfLine()'s and _IsPtLeftOfArc()'s combined with BitXOR(), it can be determinined if a point is inside or outside of that specific shape.

Because, as mention before, imagine a point traveling in a horizontal line from right to left. If the point crosses a shape's boundary once or an odd number of times then the point is inside the shape.

If the point crosses a shape's boundary no times, twice or an even number of times then the point is outside the shape.

[Progress]

Using your old _IsPtInArc() function, determining if a point is in or outside the "arc and chord" shape works.

However, determining a point on the two pie shapes do not work correctly.

Using your new _IsPtInArc() function in my example, none of the shapes worked correctly.

Here is the example I have been trying to get to work.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Array.au3>


Global $a1, $a2
Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic, $hBrush1

_Main()

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 300

    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)

    GUISetState()

    _GDIPlus_Startup()

    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

    ;arc and chord shape
    Local $iCircleX = 240, $iCircleY = 100, $iCircleWidth = 80, $iCircleHth = 80
    _GDIPlus_GraphicsDrawArc($hGraphic, $iCircleX, $iCircleY, $iCircleWidth, $iCircleHth, -30, -170)
    Local $aChPt = _ArcChord($iCircleX, $iCircleY, $iCircleWidth, $iCircleHth, -30, -170)
    _GDIPlus_GraphicsDrawLine($hGraphic, $aChPt[0], $aChPt[1], $aChPt[2], $aChPt[3])
    $hBrush1 = _GDIPlus_BrushCreateSolid(0xFFFF0000) ; Red centre of circle
    _GDIPlus_GraphicsFillEllipse($hGraphic, 278, 138, 4, 4, $hBrush1)

    ;missing pie slice shape
    Local $iCX = 60, $iCY = 10, $iCWidth = 100, $iCHth = 100, $iStartAng = 130, $iSweepAngle = 330
    _GDIPlus_GraphicsDrawArc($hGraphic, $iCX, $iCY, $iCWidth, $iCHth, $iStartAng, $iSweepAngle)
    Local $aChPt1 = _ArcChord($iCX, $iCY, $iCWidth, $iCHth, $iStartAng, $iSweepAngle)
    ;_ArrayDisplay($aChPt1)
    Local $iCentX = $iCX + $iCWidth / 2, $iCentY = $iCY + $iCHth / 2
    _GDIPlus_GraphicsDrawLine($hGraphic, $aChPt1[0], $aChPt1[1], $iCentX, $iCentY)
    _GDIPlus_GraphicsDrawLine($hGraphic, $iCentX, $iCentY, $aChPt1[2], $aChPt1[3])

    ;Pie slice shape
    Local $iCX2 = 40, $iCY2 = 120, $iCWidth2 = 300, $iCHth2 = 300, $iStartAng2 = 190, $iSweepAngle2 = 50 ; or  $iStartAng2 = -170,
    _GDIPlus_GraphicsDrawArc($hGraphic, $iCX2, $iCY2, $iCWidth2, $iCHth2, $iStartAng2, $iSweepAngle2)
    Local $aChPt2 = _ArcChord($iCX2, $iCY2, $iCWidth2, $iCHth2, $iStartAng2, $iSweepAngle2)
    Local $iCentX2 = $iCX2 + $iCWidth2 / 2, $iCentY2 = $iCY2 + $iCHth2 / 2
    _GDIPlus_GraphicsDrawLine($hGraphic, $aChPt2[0], $aChPt2[1], $iCentX2, $iCentY2)
    _GDIPlus_GraphicsDrawLine($hGraphic, $iCentX2, $iCentY2, $aChPt2[2], $aChPt2[3])

    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_BrushDispose($hBrush1)

                _GDIPlus_Shutdown()
                Exit
            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                        "Cursor left of Ist Line missing pie slice: " & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX, $iCentY, $aChPt1[2], $aChPt1[3]) & @CRLF & _
                        "Cursor left of 2nd Line missing pie slice: " & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt1[0], $aChPt1[1], $iCentX, $iCentY) & @CRLF & _
                        "Cursor left of arc: " & _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX, $iCentY, $iCWidth / 2, 290, 260) & @CRLF & _
                        "Cursor in missing pie slice shape: " & _
                        BitXOR(_IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX, $iCentY, $aChPt1[2], $aChPt1[3]), _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt1[0], $aChPt1[1], $iCentX, $iCentY), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX, $iCentY, $iCWidth / 2, 290, 260)) & @CRLF & @CRLF & _
                        "Cursor in Pie slice shape: " & _
                        BitXOR(_IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt2[0], $aChPt2[1], $iCentX2, $iCentY2), _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX2, $iCentY2, $aChPt2[2], $aChPt2[3]), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX2, $iCentY2, $iCWidth2 / 2, 240, 190)) & @CRLF & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt2[0], $aChPt2[1], $iCentX2, $iCentY2) & " " & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX2, $iCentY2, $aChPt2[2], $aChPt2[3]) & " " & _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX2, $iCentY2, $iCWidth2 / 2, 120, 170) & @CRLF & @CRLF & _
                        "Cursor in arc and chord: " & _
                        BitXOR(_IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt[0], $aChPt[1], $aChPt[2], $aChPt[3]), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCircleX + $iCircleWidth / 2, $iCircleY + $iCircleHth / 2, $iCircleWidth / 2, 30, 200)) & @CRLF & _
                        "Cursor left of line: " & _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt[0], $aChPt[1], $aChPt[2], $aChPt[3]) & @CRLF & _
                        "Cursor in Arc: " & _IsPtInArc($aPos[0], $aPos[1], $iCircleX + $iCircleWidth / 2, $iCircleY + $iCircleHth / 2, _
                        $iCircleWidth / 2, 30, 200) & @CRLF)

            Case $GUI_EVENT_PRIMARYUP
                $aPos = MouseGetPos()

        EndSwitch
    WEnd
EndFunc   ;==>_Main

;Parameter:-
; $x, $y - coordinates of point to be checked.
; $x1, $y1 - coordinates of one end of the line.
; $x2, $y2 - coordinates of the other end of the line.
; Returns True if check point is left of line, else false.
; Remarks:-
;I.  quadrant   0   to  pi/2
;II. quadrant  pi/2 to  pi
;III.quadrant  pi   to -pi/2
;IV. quadrant -pi/2 to   0
;
;           -pi/2 [270]
;       III   |   IV
;               |
; pi [180] -----|----> 0 or 2*pi [360](X positive axis)
;               |
;       II   |   I
;           pi/2 [90] (Y positive axis)
;
; Author - Malkey
Func _IsPtLeftOfLine($x, $y, $x1, $y1, $x2, $y2)
    ;Local $Maxy = Iif($y1 > $y2, $y1, $y2) ; $y must be below $Maxy; and,
    ;Local $Miny = Iif($y1 <= $y2, $y1, $y2) ; $y must be above $Miny to be true (vertically).
    ; $x on the line = (-$y * $x2 + $y * $x1 + $y1 * $x2 - $x1 * $y2) / (-$y2 + $y1)  (horizontally)
    Return ($x < (-$y * $x2 + $y * $x1 + $y1 * $x2 - $x1 * $y2) / (-$y2 + $y1) And _
            $y < Iif($y1 > $y2, $y1, $y2) And $y > Iif($y1 <= $y2, $y1, $y2))
EndFunc   ;==>_IsPtLeftOfLine

;Parameters:-
; $xL - The X coordinate of the upper left corner of the rectangle that bounds the ellipse in which to draw the arc.
; $yT - The Y coordinate of the upper left corner of the rectangle that bounds the ellipse in which to draw the arc.
; $iCircleWidth - The width of the rectangle that bounds the ellipse in which to draw the arc.
; $iCircleHth - The height of the rectangle that bounds the ellipse in which to draw the arc.
; $StAngle - The angle between the X axis and the starting point of the arc.
; $EndAngle - The angle between the starting and ending points of the arc.
;Returns an array:-
; $aRet[0]=$x1, $aRet[1]=$y1, $aRet[2]=$x2, $aRet[3]=$y2 where points ($x1, $y1) and ($x2, $y2) are the
; start and end coordinates of arc.
; ;Author - Malkey
Func _ArcChord($xL, $yT, $iCircleWidth, $iCircleHth, $StAngle, $iSweepAngle)
    Local $xR = $xL + $iCircleWidth / 2
    Local $yR = $yT + $iCircleHth / 2
    Local $Rad = $iCircleWidth / 2
    Local $pi = 4 * ATan(1), $aRet[4]

    $aRet[0] = Round($Rad * Cos($StAngle * $pi / 180) + $xR)
    $aRet[1] = Round($Rad * Sin($StAngle * $pi / 180) + $yR)
    $aRet[2] = Round($Rad * Cos(($StAngle + $iSweepAngle) * $pi / 180) + $xR)
    $aRet[3] = Round($Rad * Sin(($StAngle + $iSweepAngle) * $pi / 180) + $yR)
    Return $aRet
    ;ConsoleWrite($aRet[0] & ", " & $aRet[1] & ", " & $aRet[2] & ", " & $aRet[3] & @CRLF)
EndFunc   ;==>_ArcChord

;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $EndAngle the start and end angle in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to end angle counter clockwise
;Returns True if a horizontal line draw from the point to the right cuts the arc
;  once, otherwise returns false
;Author - martin
;               $xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw)
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $EndAngle)
    Local $pi = 4 * ATan(1), $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $Deg2Rad = $pi / 180

    ;ensure sensible angles
    While $StAngle < 0
        $StAngle = Mod($StAngle, 360)
    WEnd

    While $EndAngle < 0
        $EndAngle = Mod($EndAngle, 360)
    WEnd
    If $EndAngle <= $StAngle Then $EndAngle += 360 ; 2*$pi

    ;check obvious cases
    If $xPt - $xR >= $Rad Then Return False
    If Abs($yPt - $yR) >= $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $Alpha1 = ASin(Abs(($yPt - $yR) / $Rad)) / $Deg2Rad
    Select
        Case $yPt <= $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt > $yR
            $Alpha2 = 360 - $Alpha1
            $Alpha1 = 180 + $Alpha1
    EndSelect

    If ($Alpha1 > $StAngle And $Alpha1 <= $EndAngle) Then
        $Result1 = $xPt < ($Rad * Cos($Alpha1 * $Deg2Rad) + $xR)
    EndIf

    If ($Alpha2 > $StAngle And $Alpha2 <= $EndAngle) Or _
            ($Alpha2 + 360 > $StAngle And $Alpha2 + 360 <= $EndAngle) Then
        $Result2 = $xPt < ($Rad * Cos($Alpha2 * $Deg2Rad) + $xR)
    EndIf

    Return BitXOR($Result1, $Result2) = 1
EndFunc   ;==>_IsPtInArc
;===============================================================
Func _IsPtInArcNew($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw) ; <====== $Sw ????????????? ======
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta, $j
    Local $pi = 4 * ATan(1), $Deg2Rad = 180 / $pi


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Deg2Rad
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 and _OneIsSameAngle($StAngle,$StAngle + $sw,270) Then
        $result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)
    Return BitXOR($Result1, $Result2) = 1
EndFunc   ;==>_IsPtInArc
;=== SetAngle ==========
;converts the angle to be in range 0 to 360
func _SetAngle(ByRef $aS)
    while $aS < 0
        $aS += 360
    WEnd
    while $aS > 360
        $aS -= 360 ; <======= Corrected this ==========
    WEnd
EndFunc
Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    Local $aa, $bb
    If $sweepA >= 360 Then Return True
    $aa = $startA
    _SetAngle($aa)
    $bb = $startA + $sweepA
    _SetAngle($bb)
    If $ang = $aa Then;check if start a top or bottom type of end
        If $sweepA > 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA < 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf
    EndIf
    If $ang = $bb Then; is end a top or bottom type
        If $sweepA < 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA > 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf
    EndIf
    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf
    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd
    While $ang < $S1
        $ang += 360
    WEnd
    While $ang > $E1
        $ang -= 360
    WEnd
    Return $ang >= $S1 And $ang <= $E1
EndFunc   ;==>_AngleInRange
func _OneIsSameANgle($A,$B,$C)
    _SetAngle($A)
    _SetAngle($B)
    if $A = $C or $B = $C then return True
    return False
EndFunc
;===============================================================

; Same as _Iif() function from Misc.au3 include file
Func Iif($fTest, $vTrueVal, $vFalseVal)
    If $fTest Then
        Return $vTrueVal
    Else
        Return $vFalseVal
    EndIf
EndFunc   ;==>Iif

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

[Conclusion]

Seeing your example is working correctly and my approach is not working, I will be using your method until something better comes along.

Malkey

Link to comment
Share on other sites

I am not certain what the parameter "$Sw" in IsPtInArc() stands for, $EndAngle or $fSweepAngle?

$Sw is the sweep. I did have it as the endangle but changed it and then forgot to change the comments.

I prefer point in arc rather than point left of arc. If the arc is a circle and the point is inside the circle then it is obvious that the function is telling you the point is inside the arc. If the point is to the left of the circle it returns false which you wouldn't expect if it was called IsPtToLeftOfArc. If the arc is only say from 180 to 450 then it is not obvious that the point is in the arc if the function returns true when the point is far away to the left but below the centre of the circle. The function returns true if the horizontal line from the point to + infinity cuts the arc once. Maybe I should think of a better name. The function is "is the height of the point between the highest and lowest points of the arc that exist for values of x greater than the x position of the point".

I'll have a look at your example tonight and see if I can see why it doesn't work.

EDIT. Adding a pen parameter to the functions would be sensible so I'll do that.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Malkey, here is your example but modified.

I changed the angles in your _IsPtInArc commands, I changed the _IsPtInArc function to the latest version I have used in my previous examples, and I commented out your IsPtLeftOfLine and used my version because yours seemed to give the wrong result when the cursor was at the top of the line in the arc and chord shape, but I didn't spend the time to see what the difference is.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Array.au3>


Global $a1, $a2
Global $pi = 4 * ATan(1)
Global $Rad2Deg = 180 / $pi
Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2);1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic, $hBrush1

_Main()

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 300

    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)

    GUISetState()

    _GDIPlus_Startup()

    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)

    _GDIPlus_GraphicsClear($hGraphic, 0xFFE8FFEF)

    ;arc and chord shape
    Local $iCircleX = 240, $iCircleY = 100, $iCircleWidth = 80, $iCircleHth = 80
    _GDIPlus_GraphicsDrawArc($hGraphic, $iCircleX, $iCircleY, $iCircleWidth, $iCircleHth, -30, -170)
    Local $aChPt = _ArcChord($iCircleX, $iCircleY, $iCircleWidth, $iCircleHth, -30, -170)
    _GDIPlus_GraphicsDrawLine($hGraphic, $aChPt[0], $aChPt[1], $aChPt[2], $aChPt[3])
    $hBrush1 = _GDIPlus_BrushCreateSolid(0xFFFF0000) ; Red centre of circle
    _GDIPlus_GraphicsFillEllipse($hGraphic, 278, 138, 4, 4, $hBrush1)

    ;missing pie slice shape
    Local $iCX = 60, $iCY = 10, $iCWidth = 100, $iCHth = 100, $iStartAng = 130, $iSweepAngle = 330
    _GDIPlus_GraphicsDrawArc($hGraphic, $iCX, $iCY, $iCWidth, $iCHth, $iStartAng, $iSweepAngle)
    Local $aChPt1 = _ArcChord($iCX, $iCY, $iCWidth, $iCHth, $iStartAng, $iSweepAngle)
    ;_ArrayDisplay($aChPt1)
    Local $iCentX = $iCX + $iCWidth / 2, $iCentY = $iCY + $iCHth / 2
    _GDIPlus_GraphicsDrawLine($hGraphic, $aChPt1[0], $aChPt1[1], $iCentX, $iCentY)
    _GDIPlus_GraphicsDrawLine($hGraphic, $iCentX, $iCentY, $aChPt1[2], $aChPt1[3])

    ;Pie slice shape
    Local $iCX2 = 40, $iCY2 = 120, $iCWidth2 = 300, $iCHth2 = 300, $iStartAng2 = 190, $iSweepAngle2 = 50 ; or  $iStartAng2 = -170,
    _GDIPlus_GraphicsDrawArc($hGraphic, $iCX2, $iCY2, $iCWidth2, $iCHth2, $iStartAng2, $iSweepAngle2)
    Local $aChPt2 = _ArcChord($iCX2, $iCY2, $iCWidth2, $iCHth2, $iStartAng2, $iSweepAngle2)
    Local $iCentX2 = $iCX2 + $iCWidth2 / 2, $iCentY2 = $iCY2 + $iCHth2 / 2
    _GDIPlus_GraphicsDrawLine($hGraphic, $aChPt2[0], $aChPt2[1], $iCentX2, $iCentY2)
    _GDIPlus_GraphicsDrawLine($hGraphic, $iCentX2, $iCentY2, $aChPt2[2], $aChPt2[3])

    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_BrushDispose($hBrush1)

                _GDIPlus_Shutdown()
                Exit
            Case $GUI_EVENT_MOUSEMOVE
                $aPos = MouseGetPos()
                ToolTip("Mouse Position X:  " & $aPos[0] & "   Y: " & $aPos[1] & @CRLF & @CRLF & _
                "Cursor in pie : " & _
                    BitXOR( _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX, $iCentY, $aChPt1[2], $aChPt1[3]), _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt1[0], $aChPt1[1], $iCentX, $iCentY), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX, $iCentY, $iCWidth / 2, 130, 330)) & @CRLF & _
                        "Cursor left of Ist Line missing pie slice: " & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX, $iCentY, $aChPt1[2], $aChPt1[3]) & @CRLF & _
                        "Cursor left of 2nd Line missing pie slice: " & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt1[0], $aChPt1[1], $iCentX, $iCentY) & @CRLF & _
                        "Cursor left of arc: " & _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX, $iCentY, $iCWidth / 2, 130, 330) & @CRLF & _
                        "Cursor in missing pie slice shape: " & _
                        BitXOR(_IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX, $iCentY, $aChPt1[2], $aChPt1[3]), _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt1[0], $aChPt1[1], $iCentX, $iCentY), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX, $iCentY, $iCWidth / 2, 100, 30)) & @CRLF & @CRLF & _
                        "Cursor in Pie slice shape: " & _
                        BitXOR(_IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt2[0], $aChPt2[1], $iCentX2, $iCentY2), _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX2, $iCentY2, $aChPt2[2], $aChPt2[3]), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX2, $iCentY2, $iCWidth2 / 2, $iStartAng2, $iSweepAngle2)) & @CRLF & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt2[0], $aChPt2[1], $iCentX2, $iCentY2) & " " & _
                        _IsPtLeftOfLine($aPos[0], $aPos[1], $iCentX2, $iCentY2, $aChPt2[2], $aChPt2[3]) & " " & _
                        _IsPtInArc($aPos[0], $aPos[1], $iCentX2, $iCentY2, $iCWidth2 / 2, 190, 50) & @CRLF & @CRLF & _
                        "Cursor in arc and chord: " & _
                        BitXOR(_IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt[0], $aChPt[1], $aChPt[2], $aChPt[3]), _
                        _IsPtInArc($aPos[0], $aPos[1], $iCircleX + $iCircleWidth / 2, $iCircleY + $iCircleHth / 2, $iCircleWidth / 2, -30, -170)) & @CRLF & _
                        "Cursor left of line: " & _IsPtLeftOfLine($aPos[0], $aPos[1], $aChPt[0], $aChPt[1], $aChPt[2], $aChPt[3]) & @CRLF & _
                        "Cursor in Arc: " & _IsPtInArc($aPos[0], $aPos[1], $iCircleX + $iCircleWidth / 2, $iCircleY + $iCircleHth / 2, _
                        $iCircleWidth / 2, -30, -170) & @CRLF)

            Case $GUI_EVENT_PRIMARYUP
                $aPos = MouseGetPos()

        EndSwitch
    WEnd
EndFunc   ;==>_Main

#cs
;Parameter:-
; $x, $y - coordinates of point to be checked.
; $x1, $y1 - coordinates of one end of the line.
; $x2, $y2 - coordinates of the other end of the line.
; Returns True if check point is left of line, else false.
; Remarks:-
;I.  quadrant   0   to  pi/2
;II. quadrant  pi/2 to  pi
;III.quadrant  pi   to -pi/2
;IV. quadrant -pi/2 to   0
;
;           -pi/2 [270]
;       III   |   IV
;               |
; pi [180] -----|----> 0 or 2*pi [360](X positive axis)
;               |
;       II   |   I
;           pi/2 [90] (Y positive axis)
;
; Author - Malkey
Func _IsPtLeftOfLine($x, $y, $x1, $y1, $x2, $y2)
    ;Local $Maxy = Iif($y1 > $y2, $y1, $y2) ; $y must be below $Maxy; and,
    ;Local $Miny = Iif($y1 <= $y2, $y1, $y2) ; $y must be above $Miny to be true (vertically).
    ; $x on the line = (-$y * $x2 + $y * $x1 + $y1 * $x2 - $x1 * $y2) / (-$y2 + $y1)  (horizontally)
    Return ($x < (-$y * $x2 + $y * $x1 + $y1 * $x2 - $x1 * $y2) / (-$y2 + $y1) And _
            $y < Iif($y1 > $y2, $y1, $y2) And $y > Iif($y1 <= $y2, $y1, $y2))
EndFunc   ;==>_IsPtLeftOfLine
#ce
Func _IsPtLeftOfLine($Rx, $Ry, $X1, $Y1, $X2, $Y2)
    If $Ry >= Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then
        Return False
    EndIf


    Return $Rx < ($Ry - $Y1) * ($X2 - $X1) / ($Y2 - $Y1) + $X1

EndFunc   ;==>_IsPtLeftOfLine
;Parameters:-
; $xL - The X coordinate of the upper left corner of the rectangle that bounds the ellipse in which to draw the arc.
; $yT - The Y coordinate of the upper left corner of the rectangle that bounds the ellipse in which to draw the arc.
; $iCircleWidth - The width of the rectangle that bounds the ellipse in which to draw the arc.
; $iCircleHth - The height of the rectangle that bounds the ellipse in which to draw the arc.
; $StAngle - The angle between the X axis and the starting point of the arc.
; $EndAngle - The angle between the starting and ending points of the arc.
;Returns an array:-
; $aRet[0]=$x1, $aRet[1]=$y1, $aRet[2]=$x2, $aRet[3]=$y2 where points ($x1, $y1) and ($x2, $y2) are the
; start and end coordinates of arc.
; ;Author - Malkey
Func _ArcChord($xL, $yT, $iCircleWidth, $iCircleHth, $StAngle, $iSweepAngle)
    Local $xR = $xL + $iCircleWidth / 2
    Local $yR = $yT + $iCircleHth / 2
    Local $Rad = $iCircleWidth / 2
    Local $pi = 4 * ATan(1), $aRet[4]

    $aRet[0] = Round($Rad * Cos($StAngle * $pi / 180) + $xR)
    $aRet[1] = Round($Rad * Sin($StAngle * $pi / 180) + $yR)
    $aRet[2] = Round($Rad * Cos(($StAngle + $iSweepAngle) * $pi / 180) + $xR)
    $aRet[3] = Round($Rad * Sin(($StAngle + $iSweepAngle) * $pi / 180) + $yR)
    Return $aRet
    ;ConsoleWrite($aRet[0] & ", " & $aRet[1] & ", " & $aRet[2] & ", " & $aRet[3] & @CRLF)
EndFunc   ;==>_ArcChord

;is pt in arc
;Parameters $xPt, $yPt the coords of the point
;           $xR, $yR the centre of the arc
;           $Rad the arc radius
;           $StAngle, $sw the start and sweep angle in degrees
;Only deals with circular arcs though same approach can be used with elliptical arcs.
;The arc is drawn from start angle to start angle plus sweep
;Returns True if a horizontal line draw from the point to the right cuts the arc
;       once. If the horizontal line hits an end of the arc then it returns true only if that end is a top. A top end means
;       the arc moves down away from that end.
;       If the horizontal line is a tangent to the arc then it returns false.
;Author - martin
;version 3
Func _IsPtInArc($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw)
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta, $j


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Rad2Deg
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 And _OneIsSameAngle($StAngle, $StAngle + $Sw, 270) Then
        $Result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)

    Return BitXOR($Result1, $Result2) = 1

EndFunc   ;==>_IsPtInArc

;===============================================================
Func _IsPtInArcNew($xPt, $yPt, $xR, $yR, $Rad, $StAngle, $Sw) ; <====== $Sw ????????????? ======
    Local $EndAngle, $Alpha1, $Alpha2, $Result1 = False, $Result2 = False
    Local $way = 1, $Atemp, $beta, $j
    Local $pi = 4 * ATan(1), $Deg2Rad = 180 / $pi


    ;check obvious cases
    If $xPt - $xR > $Rad Then Return False
    If Abs($yPt - $yR) > $Rad Then Return False

    ;find the angle to the point where horizontal line cuts the circle from centre of circle
    $beta = ASin(Abs(($yPt - $yR) / $Rad))
    $Alpha1 = $beta * $Deg2Rad
    Select
        Case $yPt > $yR
            $Alpha2 = 180 - $Alpha1
        Case $yPt <= $yR
            $Alpha2 = 180 + $Alpha1
            $Alpha1 = 360 - $Alpha1
    EndSelect

    $Result1 = _AngleInRange($Alpha1, $StAngle, $Sw) And ($Rad * Abs(Cos($beta)) + $xR) > $xPt
    ;ConsoleWrite("$yPt,$Alpha1, $StAngle, $Sw = " & $yPt & ', ' & $Alpha1 & ", " & $StAngle & ', ' & $Sw & @CRLF)


    ;if alpha2 is 90 or 270 then alpha1 is as well and we mustn't count the same point twice if it's the end of the arc
    ;but we only have to check 270 because 90 is the bottom which is always false if it's an end of the arc
    If $Alpha2 = 270 and _OneIsSameAngle($StAngle,$StAngle + $sw,270) Then
        $result2 = False
    Else
        $Result2 = _AngleInRange($Alpha2, $StAngle, $Sw) And (-$Rad * Abs(Cos($beta)) + $xR) > $xPt
    EndIf
    ;ConsoleWrite("$result1, $result2 = " & $Result1 & $Result2 & @CRLF)
    Return BitXOR($Result1, $Result2) = 1
EndFunc   ;==>_IsPtInArc
;=== SetAngle ==========
;converts the angle to be in range 0 to 360
func _SetAngle(ByRef $aS)
    while $aS < 0
        $aS += 360
    WEnd
    while $aS > 360
        $aS -= 360 ; <======= Corrected this ==========
    WEnd
EndFunc
Func _AngleInRange($ang, $startA, $sweepA)
    Local $S1, $E1, $Temp
    Local $aa, $bb
    If $sweepA >= 360 Then Return True
    $aa = $startA
    _SetAngle($aa)
    $bb = $startA + $sweepA
    _SetAngle($bb)
    If $ang = $aa Then;check if start a top or bottom type of end
        If $sweepA > 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA < 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf
    EndIf
    If $ang = $bb Then; is end a top or bottom type
        If $sweepA < 0 Then
            return ($ang >= 270 And $ang <= 360) Or ($ang >= 0 And $ang < 90)
        EndIf
        If $sweepA > 0 Then
            Return $ang > 90 And $ang <= 270
        EndIf
    EndIf
    If $sweepA < 0 Then
        $S1 = $startA + $sweepA
        $E1 = $startA
    Else
        $S1 = $startA
        $E1 = $startA + $sweepA
    EndIf
    While $S1 < 0
        $S1 += 360
        $E1 += 360
    WEnd
    While $ang < $S1
        $ang += 360
    WEnd
    While $ang > $E1
        $ang -= 360
    WEnd
    Return $ang >= $S1 And $ang <= $E1
EndFunc   ;==>_AngleInRange
func _OneIsSameANgle($A,$B,$C)
    _SetAngle($A)
    _SetAngle($B)

    Return BitXOR(($A = $C), ($B = $C))
EndFunc
;===============================================================

; Same as _Iif() function from Misc.au3 include file
Func Iif($fTest, $vTrueVal, $vFalseVal)
    If $fTest Then
        Return $vTrueVal
    Else
        Return $vFalseVal
    EndIf
EndFunc   ;==>Iif

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME));,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT


Func Max($A, $B)
    If $A >= $B Then Return $A
    Return $B
EndFunc   ;==>Max

Func Min($A, $B)
    If $A >= $B Then Return $B
    Return $A
EndFunc   ;==>Min
Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Func _IsPtLeftOfLine($Rx, $Ry, $X1, $Y1, $X2, $Y2)
    ;If $Ry >= Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then
;~~~~~~~~~~~~^ (Removed Equal sign)
    If $Ry > Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then

        Return False
    EndIf
    Return $Rx < ($Ry - $Y1) * ($X2 - $X1) / ($Y2 - $Y1) + $X1
EndFunc   ;==>_IsPtLeftOfLine

Martin

Using this in your corrected version of my script that you posted in Post #28, I find this modified, corrected script is working totally as intended.

Thanks Martin.

Link to comment
Share on other sites

Func _IsPtLeftOfLine($Rx, $Ry, $X1, $Y1, $X2, $Y2)
    ;If $Ry >= Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then
;~~~~~~~~~~~~^ (Removed Equal sign)
    If $Ry > Max($Y1, $Y2) Or $Ry < Min($Y1, $Y2) Then

        Return False
    EndIf
    Return $Rx < ($Ry - $Y1) * ($X2 - $X1) / ($Y2 - $Y1) + $X1
EndFunc   ;==>_IsPtLeftOfLine

Martin

Using this in your corrected version of my script that you posted in Post #28, I find this modified, corrected script is working totally as intended.

Thanks Martin.

I don't think that was wrong. Your _ArcChord function rounds the coordinates, and that means the ends of the straight lines are not at the ends of the arc and so there are gaps or cross-overs. If you remove the Round bits then it works again.

I've added a colour parameter to the line drawing functions in post #25 and improved the ability of the _CreateInnerOuterCopy function so it can deal with straight lines at any angle, but straight lines must still join arcs at a tangent, The next step is to allow straight lines and arc to join at any angle.

Also in post #25 I added an example of converting lines in a shape to pipes which is an unplanned ability of the functions.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

  • 3 years later...

Check out 

_GDIPlus_PathIsVisiblePoint
_GDIPlus_PathIsOutlineVisiblePoint

in the help file for another way in GDI+.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_PathIsOutlineVisiblePoint
; Description ...: Determines whether a specified point touches the outline of a path with the specified Graphics and Pen
; Syntax.........: _GDIPlus_PathIsOutlineVisiblePoint($hPath, $fX, $fY[, $hPen = 0[, $hGraphics = 0]])
; Parameters ....: $hPath       - Pointer to a GraphicsPath object
;                  $fX          - X coordinate of the point to test
;                  $fY          - Y coordinate of the point to test
;                  $hPen        - Pointer to a Pen object that define the width of point to test. If 0, a solid black pen with a
;                  +width of 1 will be used
;                  $hGraphics   - Pointer to a Graphics object that specifies a world-to-device transformation. If 0, the test is
;                   +done in world coordinates; otherwise, the test is done in device coordinates
; Return values .: Success      - True if the point touches the outline of the path, False otherwise
;                  Failure      - -1
; Author ........: Authenticity
; Modified.......: Eukalyptus
; Remarks .......: None
; Related .......: None
; Link ..........; @@MsdnLink@@ GdipIsOutlineVisiblePathPoint
; Example .......; Yes
; ===============================================================================================================================



; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_PathIsVisiblePoint
; Description ...: Determines whether a specified point lies in the area that is filled when a path is filled by a specified
;                  +Graphics object
; Syntax.........: _GDIPlus_PathIsVisiblePoint($hPath, $fX, $fY[, $hGraphics = 0])
; Parameters ....: $hPath       - Pointer to a GraphicsPath object
;                  $fX          - X coordinate of the point to test
;                  $fY          - Y coordinate of the point to test
;                  $hGraphics   - Pointer to a Graphics object that specifies a world-to-device transformation. If 0, the test is
;                   +done in world coordinates; otherwise, the test is done in device coordinates
; Return values .: Success      - True if the point lies in the interior of the path, False otherwise
;                  Failure      - -1
; Author ........: Authenticity
; Modified.......: Eukalyptus
; Remarks .......: None
; Related .......: None
; Link ..........; @@MsdnLink@@ GdipIsVisiblePathPoint
; Example .......; Yes
; ===============================================================================================================================
 

-> https://msdn.microsoft.com/en-us/library/windows/desktop/ms535578(v=vs.85).aspx?f=255&MSPPError=-2147217396

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...