darkshark

Sort Polygon Coordinates

18 posts in this topic

#1 ·  Posted (edited)

hi, guys, okay?
Can anyone give me a light?

I need to sort the coordinates of the vertices of a non-convex polygon, no matter whether it is clockwise, counterclockwise, from where or where it goes, just follow the "path" correctly!

I have here the image to exemplify and an array with the coordinates of the polygon in order "not correct".
 
0d3bf12.png
 
Local $XY[12][3] = [[0,0], [15,0], [15,3], [0,3], [6,3], [9,3], [9,12], [6,12], [0,12], [15,12], [15,15], [0,15]]


Here's what I tried to do, I tried to make the arctangent, arctangent 2, order from the center of the box that catches all vertices from the source and nothing has worked, since I drew on paper several times and I can not think in nothing!

Local $XY[12][3] = [[0,0], [15,0], [15,3], [0,3], [6,3], [9,3], [9,12], [6,12], [0,12], [15,12], [15,15], [0,15]]
_SortCoords($XY)
_ArrayDisplay($XY)

Func _SortCoords(ByRef $XY)
    Local $xcenter = (_ArrayMax($XY, 1, -1, -1, 0) - _ArrayMin($XY, 1, -1, -1, 0)) / 2
    Local $ycenter = (_ArrayMax($XY, 1, -1, -1, 1) - _ArrayMin($XY, 1, -1, -1, 1)) / 2

    For $i = 0 To UBound($XY) -1
        $XY[$i][2] = atan2(($ycenter - $XY[$i][1]),($xcenter - $XY[$i][0]))
    Next

EndFunc   ;==>_SortCoords


Func atan2($y, $x)
    Return (2 * ATan($y / ($x + Sqrt($x * $x + $y * $y))))
EndFunc


If anyone can help me with this I would be immensely grateful

Already thanks!

Edited by darkshark

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

13 minutes ago, darkshark said:

I need to sort the coordinates of the vertices of a non-convex polygon

What do you mean with sorting in this particular case and why you want to sort it?

How should the sorted array look like?

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

I need the points are ordered because I want to calculate the moment of inertia of the second order, the product of inertia, area, centroid, etc. in this section, this is for structural analysis!

Polygon.png

 

 
 
 

I need the coordinates follow a logical order, that part of point 1 (blue) and go to 2,3,4,5,6,7,8,9,10,11 and finish in 12

it is not necessary start from the point 1 may from another point but following the same logic!

 

Edit:

 

Here's The Coordinates of the vertices!

Polygon.jpg

Edited by darkshark

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

If the path always turns a corner, then you can set up some rules. One of the coordinates (x or y) must always repeat, but never more than once in a contiguous sequence. That prevents travelling in a straight line. eg between points 3, 4, 11, and 12. Write the code to always turn a corner et voila. You also have to select the coordinates closest to the current position when following these rules, and avoid visiting the same position twice. If the polygon has corners that are not right angles, this approach won't work.

Edited by czardas

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

I think that's not possible because you don't know how the path between the points is really.

If you draw your polygons how you have provided the draw looks like this here:

#include <Array.au3>
#include <GDIPlus.au3>

$fScale = 15
_GDIPlus_Startup()
Local $XY[13][2] = [[12], [0 * $fScale,0 * $fScale], [15 * $fScale,0 * $fScale], [15 * $fScale,3 * $fScale], [0 * $fScale,3 * $fScale], _
                          [6 * $fScale,3 * $fScale], [9 * $fScale,3 * $fScale], [9 * $fScale,12 * $fScale], [6 * $fScale,12 * $fScale], _
                          [0 * $fScale,12 * $fScale], [15 * $fScale,12 * $fScale], [15 * $fScale,15 * $fScale], [0 * $fScale,15 * $fScale]]
Local $hGUI = GUICreate("", 300, 300)
GUISetState()
$hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Local $hPen = _GDIPlus_PenCreate(0xFFFF0000)

$hPath = _GDIPlus_PathCreate()
$hMatrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixTranslate($hMatrix, 30, 30)

For $i = 1 To $XY[0][0]
    _GDIPlus_PathAddRectangle($hPath, $XY[$i][0] - 2, $XY[$i][1] - 2, 4, 4)
Next
_GDIPlus_PathTransform($hPath, $hMatrix)
_GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen)


_GDIPlus_PenSetColor($hPen, 0xFF000000)
_GDIPlus_PathReset($hPath)
_GDIPlus_PathAddPolygon($hPath, $XY)
_GDIPlus_PathTransform($hPath, $hMatrix)

_GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen)

_GDIPlus_MatrixDispose($hMatrix)
_GDIPlus_PenDispose($hPen)
_GDIPlus_PathDispose($hPath)
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_Shutdown()

Do

Until GUIGetMsg() = -3

The red squares are the coordinates and the black line represents the polygon.

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
14 minutes ago, UEZ said:

I think that's not possible

I agree. I thought I had figured it out, but it just dawned on me now after watching The X Files LOL. There isn't enough information for a general case. You beat me to it.

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

I should also watch more X-Files for some "dawn moments".

Currently I'm playing also with polygons by trying to transform a 2d world map to a 3d sphere incl. rotating "the world". It runs currently with 2 fps...

Edited by UEZ
1 person likes this

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

just out of curiosity I tried to process the given points with the traveling salesman algorithm using and adapting this script by  @RTFC , to see what would come out, but the resulting shape is far from the desired one (of course... :idiot:)

; the Travelling Salesman Problem (https://en.wikipedia.org/wiki/Travelling_salesman_problem)
; a Simulated Annealing example (combinatorial minimisation), by RTFC (22 Feb 2016)
; Adapted from Press et al. Numerical Recipes, 2nd ed., pp.438-443.

; Note that the algorithm converges on A local minimum (in terms of the
; user-defined cost-function(s)), which is not necessarily THE global minimum.
; Note also that the search path, duration, and final result may differ from run to run (city coordinates change every time).
; Several parameters and weights can be tweaked to adjust this.

#include <Array.au3>
#include <GUIConstants.au3>
#include <GDIplus.au3>
#include <Math.au3>

Global Const $GUIwidth = 600
Global Const $GUIheight = 400
Global Const $citysize = 10
Global Const $halfcitysize = $citysize / 2

$hwnd = GUICreate("Travelling Salesman Problem (using Simulated Annealing), by RTFC", $GUIwidth, $GUIheight)
GUISetState()

; Load GDI+ resources
_GDIPlus_Startup()
Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($GUIwidth, $GUIheight, $graphics)
Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)
Global $hPenLine = _GDIPlus_PenCreate(0xFF0000FF, 4)
Global $hPenCircle = _GDIPlus_PenCreate(0xFFFF0000, 4)


; Simulated Annealing vars
Global $temperat, $path, $kk, $nswap, $nswapstep, $cost, $tempstep, $absimp, $lowestcost

; initialise
SRandom(@SEC + @AutoItPID); initialise randomising seed
$verbose = True ; T: write regular progress updates to console

Local $XY[12][2] = [[0, 0],[15, 0],[15, 3],[0, 3],[6, 3],[9, 3],[9, 12],[6, 12],[0, 12],[15, 12],[15, 15],[0, 15]]
; define cities
Global $ncity = UBound($XY) ; 20
; if $ncity<10 then Exit        ; we need something to work with

Global $maxcity = $ncity * 50
Global $n[7], $xx[7], $yy[7] ; base-1 indexed
Global $x[$ncity + 1], $y[$ncity + 1], $iorder[$ncity + 1], $jorder[$maxcity + 1] ; base-1 indexed

;______START OF ANNEALING ROUTINE____________

$nover = 100 * $ncity ; maximum number of paths at any temperature
$nlimit = 10 * $ncity ; maximum number of successful path changes before continuing
$nwrite = Int($nover / 5) ; default status update interval if verbose=.t.
$tempsteps = 100 ; number of temperature steps to try
$tfactor = 0.90 ; annealing schedule: temperature is reduced by this factor after each step
$path = 0

While True
    $temperat = 0.5 ; initial temperature; smaller = more aggressive + more myopic search
    $absimp = 0 ; counter
    $nswapstepzero = 0 ; counter

    ; prep the buffers
    For $cc = 1 To 6
        $n[$cc] = 0
    Next


    For $cc = 0 To $ncity - 1
        $x[$cc] = 0.2 + $XY[$cc][0] * 0.020 ; Random()
        $y[$cc] = 0.2 + $XY[$cc][1] * 0.020 ; Random()
        $iorder[$cc] = $cc
        $jorder[$cc] = 0
    Next

    For $cc = $ncity + 1 To $maxcity
        $jorder[$cc] = 0
    Next

    ; prep the cost vars
    _CalcPathLength()
    $initcost = $path
    $lowestcost = $path

    ; main loop starts here
    For $tempstep = 1 To $tempsteps ; try up to N temperature steps
        $nswap = 0
        $nswapstep = 0

        For $kk = 1 To $nover
            $n[1] = Random(1, $ncity, 1) ; choose beginning and end of segment
            $n[2] = Random(1, $ncity, 1)
            If $n[2] >= $n[1] Then $n[2] = 1 + Mod(($n[2] + 1), $ncity)

            ; count number of cities not on segment ($nn)
            $nn = 1 + Mod(($n[1] - $n[2] + $ncity - 1), $ncity)
            If $nn < 3 Then ContinueLoop

            ; decide whether to do a segment transport or reversal (equal chances)
            $doTransport = (Random() <= 0.5)
            If $doTransport Then ; try a segment transport
                $n[3] = $n[2] + Int(Abs($nn - 2) * Random()) + 1
                $n[3] = 1 + Mod($n[3] - 1, $ncity) ; transport to a location not on the path
                _TransportCost()

            Else ; try a reversal instead
                _ReversalCost()
            EndIf

            ; Listen to the wind, talk to the trees...
            Switch _AskOracle()
                Case True
                    $nswap += 1
                    $path += $cost
                    If $doTransport Then
                        _DoTransport()
                    Else
                        _DoReversal()
                    EndIf

                    If $lowestcost > $path Then
                        $nswapstep += 1
                        $absimp += 1
                        $lowestcost = $path
                    EndIf

                    If $nswap >= $nlimit Then ExitLoop
            EndSwitch
        Next

        If $verbose Then _ScreenOut()
        If $nswapstep = 0 Then $nswapstepzero += 1
        If $nswapstepzero = 30 Then ExitLoop ; no more improvements in the last N temperature steps

        ; reduce temperature = likelihood of following a trajectory away from the nearest LOCAL optimum (in the hope of getting nearer to the GLOBAL optimum)
        $temperat *= $tfactor
    Next

    ; show final result
    MsgBox($MB_OKCANCEL, "Simulated Annealing Test Result", "Shortest Path Length: " & $lowestcost)
    Exit

WEnd

_GDIclose()
Exit


Func _AskOracle()

    If $cost < 0 Then
        Return True
    Else ; this is where all the magic happens!
        Return (Random() < Exp(-($cost / $temperat)))
    EndIf

EndFunc   ;==>_AskOracle


Func _CalcPathLength()

    $path = 0 ; Global var
    Local $cc, $index1, $index2
    For $cc = 1 To $ncity - 1
        $index1 = $iorder[$cc]
        $index2 = $iorder[$cc + 1]
        $path += _Distance($x[$index1], $x[$index2], $y[$index1], $y[$index2])
    Next
    $index1 = $iorder[$ncity] ; close the loop by tying path ends together
    $index2 = $iorder[1]
    $path += _Distance($x[$index1], $x[$index2], $y[$index1], $y[$index2])

EndFunc   ;==>_CalcPathLength


Func _Distance($x1, $x2, $y1, $y2)

    Return Sqrt((($x1 - $x2) ^ 2) + (($y1 - $y2) ^ 2))
EndFunc   ;==>_Distance


Func _ReversalCost()

    $n[3] = 1 + Mod(($n[1] + $ncity - 2), $ncity) ; find the city before n[1]...
    $n[4] = 1 + Mod($n[2], $ncity) ; and after n[2]

    ; find coordinates of the four cities
    Local $ii, $jj, $dex
    For $jj = 1 To 4
        $dex = $n[$jj]
        $ii = $iorder[$dex]
        $xx[$jj] = $x[$ii]
        $yy[$jj] = $y[$ii]
    Next

    ; calculate the cost of disconnecting the segment at both ends and reconnecting in the opposite order
    $cost = -_Distance($xx[1], $xx[3], $yy[1], $yy[3])
    $cost -= _Distance($xx[2], $xx[4], $yy[2], $yy[4])
    $cost += _Distance($xx[1], $xx[4], $yy[1], $yy[4])
    $cost += _Distance($xx[2], $xx[3], $yy[2], $yy[3])

EndFunc   ;==>_ReversalCost


Func _DoReversal()

    Local $mm = (1 + Mod(($n[2] - $n[1] + $ncity), $ncity)) * .5
    Local $ii, $jj, $ll, $itmp
    For $jj = 1 To $mm
        $ii = 1 + Mod(($n[1] + $jj - 2), $ncity)
        $ll = 1 + Mod(($n[2] - $jj + $ncity), $ncity)

        $itmp = $iorder[$ii]
        $iorder[$ii] = $iorder[$ll]
        $iorder[$ll] = $itmp
    Next

EndFunc   ;==>_DoReversal


Func _TransportCost()

    $n[4] = 1 + Mod($n[3], $ncity) ; find the city following n[3]
    $n[5] = 1 + Mod(($n[1] + $ncity - 2), $ncity) ; find the city before n[1]...
    $n[6] = 1 + Mod($n[2], $ncity) ; and after n[2]

    ; find coordinates of the six cities
    Local $jj, $dex
    For $jj = 1 To 6
        $dex = $n[$jj]
        $ii = $iorder[$dex]
        $xx[$jj] = $x[$ii]
        $yy[$jj] = $y[$ii]
    Next

    ; calculate the cost of disconnecting the path segment n1->n2, opening a space between n3-n4, connecting the segment in the space, and conencting n5 to n6
    $cost = -_Distance($xx[2], $xx[6], $yy[2], $yy[6])
    $cost -= _Distance($xx[1], $xx[5], $yy[1], $yy[5])
    $cost -= _Distance($xx[3], $xx[4], $yy[3], $yy[4])
    $cost += _Distance($xx[1], $xx[3], $yy[1], $yy[3])
    $cost += _Distance($xx[2], $xx[4], $yy[2], $yy[4])
    $cost += _Distance($xx[5], $xx[6], $yy[5], $yy[6])

EndFunc   ;==>_TransportCost


Func _DoTransport()

    Local $m1, $m2, $m3, $pp
    $m1 = 1 + Mod(($n[2] - $n[1] + $ncity), $ncity) ; find # cities from n1->n2
    $m2 = 1 + Mod(($n[5] - $n[4] + $ncity), $ncity) ; find # cities from n4->n5
    $m3 = 1 + Mod(($n[3] - $n[6] + $ncity), $ncity) ; find # cities from n6->n3

    Local $mm = 1
    For $pp = 1 To $m1
        $jj = 1 + Mod($pp + $n[1] - 2, $ncity)
        $jorder[$mm] = $iorder[$jj]
        $mm += 1
    Next

    For $pp = 1 To $m2
        $jj = 1 + Mod($pp + $n[4] - 2, $ncity)
        $jorder[$mm] = $iorder[$jj]
        $mm += 1
    Next

    For $pp = 1 To $m3
        $jj = 1 + Mod($pp + $n[6] - 2, $ncity)
        $jorder[$mm] = $iorder[$jj]
        $mm += 1
    Next

    For $pp = 1 To $ncity
        $iorder[$pp] = $jorder[$pp]
    Next

EndFunc   ;==>_DoTransport


Func _ScreenOut()

    ConsoleWrite("Simulated Annealing. Initial Path length: " & $initcost & @CRLF)
    ConsoleWrite("Step: " & $tempstep & " of " & $tempsteps & "; Temperature: " & $temperat & @CRLF)
    ConsoleWrite("Executed Swaps: " & $nswap & "; shortest Path length: " & $lowestcost & @CRLF)
    ConsoleWrite("Total Improvements: " & $absimp & "; Improvements this step: " & $nswapstep & @CRLF & @CRLF)
    _DrawTSroute()

EndFunc   ;==>_ScreenOut


Func _DrawTSroute()

    _GDIPlus_GraphicsClear($backbuffer)

    For $cc = 1 To $ncity - 1
        $index1 = $iorder[$cc]
        $index2 = $iorder[$cc + 1]
        _DrawLine($x[$index1], $x[$index2], $y[$index1], $y[$index2])
    Next
    $index1 = $iorder[$ncity] ; close the loop by tying path ends together
    $index2 = $iorder[1]
    _DrawLine($x[$index1], $x[$index2], $y[$index1], $y[$index2])
    _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $GUIwidth, $GUIheight)

EndFunc   ;==>_DrawTSroute


Func _DrawLine($x1, $x2, $y1, $y2)

    Local $x1scaled = Round($GUIwidth * $x1, 0)
    Local $y1scaled = Round($GUIheight * $y1, 0)
    Local $x2scaled = Round($GUIwidth * $x2, 0)
    Local $y2scaled = Round($GUIheight * $y2, 0)

    _GDIPlus_GraphicsDrawArc($backbuffer, $x1scaled - $halfcitysize, $y1scaled - $halfcitysize, $citysize, $citysize, 0, 360, $hPenCircle)
    _GDIPlus_GraphicsDrawLine($backbuffer, $x1scaled, $y1scaled, $x2scaled, $y2scaled, $hPenLine)

EndFunc   ;==>_DrawLine


Func _GDIclose()

    _GDIPlus_PenDispose($hPenLine)
    _GDIPlus_PenDispose($hPenCircle)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()

EndFunc   ;==>_GDIclose

 


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I think the given case is solvable, but the general case is not. My idea is to always try to turn back the way you came (clockwise or anticlockwise). As soon as you add a few more coordinates though, the problem will acquire multiple solutions and become unsolvable. How to differentiate those patterns which only have one solution (given a set of rules) is unclear to me. The rules are not clearly defined anyway, but it's still interesting.

Edited by czardas

Share this post


Link to post
Share on other sites

Got it, guys, I also was not finding a solution so I decided to ask for help here to see if anyone could help me!

But the way I have to think of another way to do it!

But anyway, thank you all!



@Chimp
I loved this script, I had never seen, he makes clear my problem hahaha.

@UEZ and @czardas

Thank you for trying to help me!

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

5 minutes ago, czardas said:

Gee that's a bit clunky. :D

Well, that's the limit of AutoIt. Have a look to the alpha version.

;coded by UEZ build 2016-04-08
#pragma compile(Icon, "c:\Program Files (x86)\AutoIt3\Icons\au3.ico")
#AutoIt3Wrapper_Run_Au3Stripper=y
#Au3Stripper_Parameters=/so /pe /rm
#AutoIt3Wrapper_Run_After=del /f /q "%scriptdir%\%scriptfile%_stripped.au3"5

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

_GDIPlus_Startup()
Global $hGUI, $iFPS = 0, $iShowFPS = 0, $bExit, $i
Global Const $iW = 947, $iH = 620, $iWh = $iW / 2, $iHh = $iH / 2, $sTitle = "GDI+ 3D Object Rotation v1.2 alpha"
Global Const $fPi = ACos(-1), $fRad = $fPi / 180, $fDeg = 180 / $fPi

AutoItSetOption("GUIOnEventMode", 1)

GDIPlus_3DRotation()

AutoItSetOption("GUIOnEventMode", 0)
_GDIPlus_Shutdown()


Func GDIPlus_3DRotation()
    $bExit = False
    $hGUI = GUICreate($sTitle, $iW, $iH) ;, -1, -1, $WS_POPUP)
    GUISetState(@SW_SHOW, $hGUI)

    ;create canvas elements
    Local Const $hDC = _WinAPI_GetDC($hGUI)
    Local Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iW, $iH)
    Local Const $hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC)
    Local Const $DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap)
    Local Const $hCanvas = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hCanvas, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsSetPixelOffsetMode($hCanvas, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)

    Local Const $hBrush_Clr = _GDIPlus_BrushCreateSolid(0xFF303030), _
                $hBrush_FPS = _GDIPlus_BrushCreateSolid(0xFFA0A0A0), _
                $hBrush_Fill = _GDIPlus_BrushCreateSolid(0xFFFFFFFF), _
                $hBrush_Fill2 = _GDIPlus_BrushCreateSolid(0x10FFFFFF), _
                $hPen_Line = _GDIPlus_PenCreate(0xFF40B040, 1), _
                $hFormat_FPS = _GDIPlus_StringFormatCreate(), _
                $hFamily_FPS = _GDIPlus_FontFamilyCreate("Arial"), _
                $hFont_FPS = _GDIPlus_FontCreate($hFamily_FPS, 8), _
                $tLayout_FPS = _GDIPlus_RectFCreate(0, 0, 60, 16)

    _GDIPlus_PenSetLineJoin($hPen_Line, 2)

    $iFPS = 0

    Local Const $hPath = _GDIPlus_PathCreate(), $sPolygon = BinaryToString(_Polygons())
    Add_Polygon($sPolygon, $hPath)

    Local $aData = _GDIPlus_PathGetData($hPath)
    ConsoleWrite($aData[0][0] & @CRLF)

    Local $aSphere = CreateSphere($aData, $iWh, $iHh, 130)
    Local $iAmountDots = $aSphere[0], $tCoords = $aSphere[1], $tTypes = $aSphere[2]

    Local $fRotX = 0 * $fDeg, $fRotY = 0, $fRotZ = 10 * $fDeg, $iFillMode = 0, $i

    Local $tPoints = DllStructCreate("float dots[" & 2 * $iAmountDots & "]")

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit_About")
    AdlibRegister("CalcFPS", 1000)

    Do
        DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush_Clr, "float", 0, "float", 0, _
                "float", $iW, "float", $iH) ;erase canvas background

        For $i = 1 To $iAmountDots
            Translate3Dto2D($tCoords, $i, $fRotX, $fRotY, $fRotY - $fRotX, $iWh, $iHh, 1000)
            $tPoints.dots((2 * $i - 1)) = $tCoords.fX(($i))
            $tPoints.dots((2 * $i)) = $tCoords.fY(($i))
        Next

        $hPath2 = DllCall($__g_hGDIPDll, "int", "GdipCreatePath2", "struct*", $tPoints, "struct*", $tTypes, "int", $iAmountDots, "int", $iFillMode, "handle*", 0)[5]

        DllCall($__g_hGDIPDll, "int", "GdipFillPath", "handle", $hCanvas, "handle", $hBrush_Fill2, "handle", $hPath)
        DllCall($__g_hGDIPDll, "int", "GdipFillPath", "handle", $hCanvas, "handle", $hBrush_Fill, "handle", $hPath2)
        DllCall($__g_hGDIPDll, "int", "GdipDrawPath", "handle", $hCanvas, "handle", $hPen_Line, "handle", $hPath2)

        DllCall($__g_hGDIPDll, "int", "GdipDeletePath", "handle", $hPath2)

        $fRotX += 0.025
        $fRotY += 0.033

        _GDIPlus_GraphicsDrawStringEx($hCanvas, "FPS: " & $iShowFPS, $hFont_FPS, $tLayout_FPS, $hFormat_FPS, $hBrush_FPS) ;draw background message text
        _WinAPI_BitBlt($hDC, 0, 0, $iW, $iH, $hDC_backbuffer, 0, 0, $SRCCOPY) ;blit drawn bitmap to GUI

        $iFPS += 1
        If $bExit Then ExitLoop
    Until Not Sleep(10)

    AdlibUnRegister("CalcFPS")
    ;release resources
    _GDIPlus_PathDispose($hPath)
    _GDIPlus_PathDispose($hPath2)
    _GDIPlus_FontDispose($hFont_FPS)
    _GDIPlus_FontFamilyDispose($hFamily_FPS)
    _GDIPlus_StringFormatDispose($hFormat_FPS)
    _GDIPlus_BrushDispose($hBrush_Clr)
    _GDIPlus_BrushDispose($hBrush_FPS)
    _GDIPlus_BrushDispose($hBrush_Fill)
    _GDIPlus_BrushDispose($hBrush_Fill2)
    _GDIPlus_PenDispose($hPen_Line)
    _GDIPlus_GraphicsDispose($hCanvas)
    _WinAPI_SelectObject($hDC_backbuffer, $DC_obj)
    _WinAPI_DeleteDC($hDC_backbuffer)
    _WinAPI_DeleteObject($hHBitmap)
    _WinAPI_ReleaseDC($hGUI, $hDC)
    GUIDelete($hGUI)
EndFunc   ;==>GDIPlus_3DRotation

Func Translate3Dto2D(ByRef $tStruct, $iPos, $fRotX, $fRotY, $fRotZ, $fCenterX = 0, $fCenterY = 0, $fZDeepCorrection = 1000)
    Local Const $fCosRotX = Cos($fRotX), $fSinRotX = Sin($fRotX), _
                $fCosRotY = Cos($fRotY), $fSinRotY = Sin($fRotY), _
                $fCosRotZ = Cos($fRotZ), $fSinRotZ = Sin($fRotZ), _
                $f1 = $fCosRotY * $tStruct.x(($iPos)), _
                $f2 = $fSinRotX * $tStruct.y(($iPos)), _
                $f3 = $fCosRotX * $tStruct.z(($iPos)), _
                $f4 = $fCosRotX * $tStruct.y(($iPos)), _
                $f5 = $fSinRotX * $tStruct.z(($iPos)), _
                $f6 = $f1 - $fSinRotY * ($f2 + $f3), _
                $fXPos = $fCosRotZ * $f6 - $fSinRotZ * ($f4 - $f5), _
                $fYPos = $fSinRotZ * $f6 + $fCosRotZ * ($f4 - $f5), _
                $fZPos = $fSinRotY * $tStruct.x(($iPos)) + $fCosRotY * ($f2 + $f3), _
                $fZPerspCorrection = 1 / ($fZPos / $fZDeepCorrection + 1)
    $tStruct.fX(($iPos)) = $fXPos * $fZPerspCorrection + $fCenterX
    $tStruct.fY(($iPos)) = $fYPos * $fZPerspCorrection + $fCenterY
EndFunc   ;==>Translate3Dto2D

Func _Exit_About()
    $bExit = True
EndFunc   ;==>_Exit_About

Func CalcFPS() ;display FPS
    $iShowFPS = $iFPS
    $iFPS = 0
EndFunc   ;==>CalcFPS

Func CreateSphere($aData, $iWh, $iHh, $fRadius = 200)
    Local $iAmountDots = $aData[0][0]
    Local $tCoords = DllStructCreate("struct;float x[" & $iAmountDots & "];float y[" & $iAmountDots & "];float z[" & $iAmountDots & "];float fX[" & $iAmountDots & "];float fY[" & $iAmountDots & "];float fZ[" & $iAmountDots & "];endstruct")
    Local $tTypes = DllStructCreate("byte type[" & $iAmountDots & "]")
    Local $i, $fLongitude, $fLatitude
    For $i = 1 To $iAmountDots
        $fLongitude = ($iWh - $aData[$i][0]) / $fRadius
        $fLatitude = 2 * ATan(2.718281828^(($iHh - $aData[$i][1]) / $fRadius)) - ($fPi / 2)
        $tCoords.x(($i)) = $fRadius * Cos($fLatitude) * Cos($fLongitude)
        $tCoords.y(($i)) = $fRadius * Cos($fLatitude) * Sin($fLongitude)
        $tCoords.z(($i)) = $fRadius * Sin($fLatitude)
        $tTypes.type(($i)) = $aData[$i][2]
    Next
    Local $aResult[3] = [$iAmountDots, $tCoords, $tTypes]
    Return $aResult
EndFunc

Func Add_Polygon($sPolygon, $hPath, $fScale = 1.0)
    Local $aPolygons = StringRegExp($sPolygon, "(?mi)polygon\((.*)\)", 3), $i, $j, $k, $aPolygon, $tPoints
    For $i = 0 To UBound($aPolygons) - 1
        $aPolygon = StringRegExp($aPolygons[$i], "\d*\.?\d+", 3)
        $tPoints = DllStructCreate("float coordinates[" & UBound($aPolygon) & "]")
        $k = 1
        For $j = 0 To UBound($aPolygon) - 2 Step 2
            $tPoints.coordinates((2 * $k - 1)) = $aPolygon[$j] * $fScale
            $tPoints.coordinates((2 * $k)) = $aPolygon[$j + 1] * $fScale
            $k += 1
        Next
        DllCall($__g_hGDIPDll, "int", "GdipAddPathPolygon", "handle", $hPath, "struct*", $tPoints, "int", UBound($aPolygon) / 2)
        $tPoints = 0
    Next
EndFunc

;Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2015-09-19

Func _Polygons($bSaveBinary = False, $sSavePath = @ScriptDir)
    Local $Polygons
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= 'NYIpNIHogAtjgSkARTAgOQBigQs0K4MFgh03gEc5AngzNQ3BFznDJsAUMyAxMOY2AwkBBjExgA0BAwBE4wADhiQ4IDFAXMBvwRVFQAYzQmkzNDhAXDFfQFdBHEAfQQaDKDUCEDMrQpABAzUAAzkCEDU1/QCAMYAeQgYCEAADwQxARtY2ghYBHTbBUzFATwEtWjiBhjHAb4EJOMGjMU/BkQADQDXAGTA5gSM010CdwBkFAzYCAzMCA0F7CwADgmo0wDg3IDk16UEjNDGCTDHBEkEMgkwrwblCszhCqTTAyTkgvjiAR8ELQHKBXoBPNIJ8p4AmwgKAEyA4gl40g3nGN8IFQE0xIDbAWcEI/jjBBcI6AqaEhcHZgI6CZPeBzAHBgtczQrrDJgBCAKD/gtDDL8B9wRHAFMCvgnnBBfYxQETDCDEC4EFPwS9Av7IwQlI5OMFvQiw0oHzf4AXgfuUagQ+DJTAAWqJCocAkNiAyOAI8OCBR7iDgVuEuYAE4AFcDMqGFt6CAoTtgATjhBaFDNwBL/+EFYgHhI0Q7YATgC8NR4AK+MuEOYgFhHOACAUM25AX5YRA2NOAIQElhBwJGZQH+NmAcYATCXYF6I5HBWmAEvjLiFGABYgfBXUBTNCAC/2IHwAPgAkBEYwEAgsNmYwH/xHjhMiGMQ3rhhGIKYDfAhP/jCOA7AJCAMGEHYToAEeEF/2ABYJEAROMIwHtiQEqGZgHbaYqCFzkCPWFtNWF1gnD9gUE5AqpjgWQB4D3gBYJZ+jNgGDThfOSF5whlAQgN/yFfoFokWaJXpD8hMqBgIUTZYAQzIEA9omM54AJlBO9pB2UBqRhgBjVAXeNDIA/vQJogTIJOYZE2gAZBy2AK5jiAoENfMTYhAwBv4l39QRw14BoBWOFJggGia4HObjWAgMEEoDk1gAFjeTO14Ws1Y6E04JxgBjij1teAa4EBQpM0AK02ggEBCP9gS2EGA2UhDIIBYcaggeEMfcIENcN1JAPgOUMLAcgy/cIEN2AKwcSDvYQBodYFCL9AQcEEIBSAAWCAIBA3Ajv2NQCFgMU3Q+WhhoAB4mT/AQQACIABAeKAZiEDQAKHAdViBjagmjBlIDaA12ET3WLDNmAt4RkiUjagfYAB76BJYgLDALI5NpAOURhygL42wkKVAcE4shaAFzYQFV/xDNMEUFyhBQIuNrJaNftQVOEINzIDcVnBACAKwADd8kk24FRhbqIfNtACcQaPMhDBAOAigQwsIDdiWN414C3CAOMIkg434CIxc/1CLTdCdrILwQBRGLEjxAC78QwCWDcgGaEFEkk3AYm7wCeyCTcQNcEAsgk34VT7wACyFjewOgAExQDxamUC/8AAkQGQHcAAsCNwLXAI8TZ3Gi/HAEgxMtB+MAYjAjK9YBI2kARANcEAkR42kDfdcBYyQBWjCCAPMpAPkQHv8CsxhhMyEiUz0AJBF6NZ+/E05RgzoAODGkFPMBORK//CHcQAcFnhTYCfAATFAPANfYUnMwAUEBigVgKMsUE1/3EyY1BgAsFZI48xA6CelgHvBASUAaQFUQs1gF6CCjMt/2IPwQDQIVN2UVVhLEAZY1XvUQtzVfJ0lCsz9BxzFgFl//IcIlrBDaESYlFiAjAFhFn/cBODGlsYxwCJGpKM5RiSLrthBZAEMhB74RiCDTLwZ98hHBIYwQAxBnJTMtKPAQf9QBcykkiRHtEH8mjMAMIt/DI0IiwzjhwIxgApVlFT31ce80nzEsERFTgz1DTDE+8zA6M1xQBSHjJwvaAIYAT/RCfTNHEmMAE2WjMD0UPCAP+xOeE40ReAR6AY0QbBAEJe/7M54ShhAuOq8aXiRTIDKgzvxgCpGBFglQQygGRxCVIu95EBcRnSJzIABSESQB/1D/9hApEUkwHzP9wExgBpFaMr99AcEi5RkTVAH0ENUB+gK//QYzIpAlQgMhIOOgPGAKrC/eE+NYBFwgPCNkAiVIDgMf9RRqMuMDkh'
    $Polygons &= 'J7WFNgPGAGoF78AnAgryirGdNSAtwo4SIf/AAAEKUI1xDGLSPgPEAGoF/cHTNWHDIQICajCO0gpxIv41BYxhTsEAMgbRu2ECtDi3CATGADgGN9C+Ea04Yl73cQqQeRInN7ATsJMBNcMA3wCWs0gxA5AB47Q3EEWgsv/wGDFfcqfGANLaBAShbKUF/jgCh5EBQArBAJABoAcwL944gCQAnpBNMAM4MD1AB/42IJfBAPFYkQFiAjK5AW/7wQChYTRhq2MCUKGVAWEVbjRACXEG8p80kC1QCzhvMarAANMEchk0YDswEDj90p408ILRBCAK0QQzAyAKX7EJkwEQBmEPkk04IrM0n3Cs0QQgCvGqshk4NkAFD+IVIQyRDFOePbcALCA4NTkuMSAgNDEyLjIDwDggIDM5NC40AWA1LqI1ADAxLjEBMDQBMCI4BDAyLjQGMDQ1AC4zIDQwNC43RQEYMQAyNDA1AjIzKjICgDYDGDcCgDIuQjkAGDI4LjIGgDGINy45AAw0LjABDCcAOgAzA44xMAJAMy4WMwMMABk4AEYsIDe1AJUzABk5ATMBDDcAdBECJjc4OABNNDA3lQFANwBhOAYMNjYATaA0MTMuNgEMMQCBDjQAhwEgBwYpDQpwAG9seWdvbig4XDI1ASsAX4E+MgBPIK41gDGBjAAGMwAGOAMGWDkuNgIGAV8zgxk4vC44gQwKIAYGiDE5gEYYMCA0gIoAHjkxNPcBxQB3AB45gMiBF4DOAAbrgGABODMFBjcABoACBgY3ARYBBoHlNQAjAJE5Mt4zAhMDLQIGhSYygaQFBn8CXEEgACmMIwYDSSwAFDQ1Rx81AE41AArBcTk390EGABfAVzgAOkAfAEqAIj44AGhBBgALAAMAFDUgtDUzQ1I3gJpABjmCCfY3gGYAAzYCEMBxgAlAE//ADAwdBgPKJYANwHBAjIEI94BZAAMENTBBhEB3AQ/AKu8AqAAcwlhCRTIAV8MMChD7BAPIGDcAFMCjwKtBkAADFcCwMUISNwAUMCAz/jNApQADgAEHA4DHgK2Az/HAvTc1MMHXAdYBA4E7lDM0A6c0gW4zNELe9Dc0gsczhBYMHQQDySXaNgGOM4DbwRg2ABQAA/o2QhI3QD1CBgEDQMPAJXOAgkESODaBCYABoQ85f0EkZRkgcYAU4ELCaeElM/PgS0ELODCCAeJeoQlAEdQyMaIJN4FgM+FigQH/RQvBBMARoAmBZIEBoGTAEb+DDqsWhgEJG8AKQRE5xQr/gBQgIOA4IQMAgGAMISngEt+hD0YRaAaGAckKOOBNgC13AmChh2EyMcIQACHACjX+NuOKhQGhIsByICmFAUIk8jRjLDk14RKAAeESgGC/gAHABMIqog+AAUGjMOIlX0CnwgQiA2AGgpk44Qw0/jNCo6BboQnCUGEGwAQAQfvCEeFrMyCsAhViLIUBgyf/IlxkE8Ct4R9AC2AGoJKiCf8gDCIDwXBAd2AmgAFBdwCH/8FEA61BmcJXwXDguqFJ43hfwBHBBIIBQQvBBDIDIjV/4gxjOaC3gQEjVoAoYS01/0NLCS+HAamuoJcBDuMf4E6/ICPAF+LEAc2hHMEkMSF8/4YBYstAXuLEg2dDHsAEQR6/4CNmyySP6wyGAQrAMCEc/0AX4gVgQiI2YgzjPyIcwQr/gQECTqEPgTQgOmG+QtbABP+CAUJ3xASBcMIEIsjCKkALvyHIig6HAclXAIegFTViDOtBigAONuKkN6BY4AXA2fuBLYP5NsLJ4WtgBqAAwnD/Yhnh4SEyUHjCAKEbIFjRBPliFTc3IiLAAJJEMhZgAlMyNpIkNjVyKTdCTTb9wlY3YAAxA5AzE06ICsYAf6o4Ei7VB1JEAAfiITJJNv+iYTFJEQuTBDoDxwBqBbKL/3EOIQICOoBI8gLQBZIEYgX/YluQAQJNAi1ADWICDATEAP85BkNT4BMiAlInwAASQfJI/0AScjISEcUAOQPHAGoF'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= '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'
    $Polygons &= 'OQIMMgMM9QEzMgMZNgRaAmcKgQYMACk='
    $Polygons = _WinAPI_Base64Decode($Polygons)
    If @error Then Return SetError(1, 0, 0)
    Local $tSource = DllStructCreate('byte[' & BinaryLen($Polygons) & ']')
    DllStructSetData($tSource, 1, $Polygons)
    Local $tDecompress
    _WinAPI_LZNTDecompress($tSource, $tDecompress, 69852)
    If @error Then Return SetError(3, 0, 0)
    $tSource = 0
    Local Const $bString = Binary(DllStructGetData($tDecompress, 1))
    If $bSaveBinary Then
        Local Const $hFile = FileOpen($sSavePath & "\Polygon.txt", 18)
        If @error Then Return SetError(2, 0, $bString)
        FileWrite($hFile, $bString)
        FileClose($hFile)
    EndIf
    Return $bString
EndFunc   ;==>_Polygons

Func _WinAPI_Base64Decode($sB64String)
    Local $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0)
    If @error Or Not $aCrypt[0] Then Return SetError(1, 0, "")
    Local $bBuffer = DllStructCreate("byte[" & $aCrypt[5] & "]")
    $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "struct*", $bBuffer, "dword*", $aCrypt[5], "ptr", 0, "ptr", 0)
    If @error Or Not $aCrypt[0] Then Return SetError(2, 0, "")
    Return DllStructGetData($bBuffer, 1)
EndFunc   ;==>_WinAPI_Base64Decode

Func _WinAPI_LZNTDecompress(ByRef $tInput, ByRef $tOutput, $iBufferSize)
    $tOutput = DllStructCreate("byte[" & $iBufferSize & "]")
    If @error Then Return SetError(1, 0, 0)
    Local $aRet = DllCall("ntdll.dll", "uint", "RtlDecompressBuffer", "ushort", 0x0002, "struct*", $tOutput, "ulong", $iBufferSize, "struct*", $tInput, "ulong", DllStructGetSize($tInput), "ulong*", 0)
    If @error Then Return SetError(2, 0, 0)
    If $aRet[0] Then Return SetError(3, $aRet[0], 0)
    Return $aRet[6]
EndFunc   ;==>_WinAPI_LZNTDecompress

The background map is the original map saved as polygons. The rotating world is the transformation of that map.

Edited by UEZ
3 people like this

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

@UEZ that's beautiful. :thumbsup:

Edited by czardas
1 person likes this

Share this post


Link to post
Share on other sites

Wow, that's Fantastic, UEz *-* :D

Share this post


Link to post
Share on other sites

I just... I don't even know how you do what you do UEZ Lol

4-5 fps on my computer.

Share this post


Link to post
Share on other sites

@darkshark,

There is of course no unique "solution" to the question asked, at least in the general case (even as simple as your I-beam).

To convince you, try to persuade yourself that the "most logical path" could well be the following (code freely borrowed to UEZ):

#include <Array.au3>
#include <GDIPlus.au3>

Local $nPoints = 12
Local $fScale = 20
_GDIPlus_Startup()
Local $XY[$nPoints + 1][2] = [ _
    [$nPoints], _
    [ 0,  0], _
    [15,  0], _
    [ 9,  3], _
    [15,  3], _
    [ 9, 12], _
    [15, 12], _
    [15, 15], _
    [ 0, 15], _
    [ 6, 12], _
    [ 0, 12], _
    [ 6,  3], _
    [ 0,  3] _
]
For $i = 1 To $nPoints
    $XY[$i][0] = $XY[$i][0] * $fScale + 50
    $XY[$i][1] = $XY[$i][1] * $fScale + 50
Next
Local $hGUI = GUICreate("", 20 * $fScale + 25, 20 * $fScale + 25)
GUISetState()
$hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Local $hPen = _GDIPlus_PenCreate(0xFFFF0000)

$hPath = _GDIPlus_PathCreate()
$hMatrix = _GDIPlus_MatrixCreate()
;~ _GDIPlus_MatrixTranslate($hMatrix, 30, 30)

For $i = 1 To $nPoints
    _GDIPlus_PathAddRectangle($hPath, $XY[$i][0] - 2, $XY[$i][1] - 2, 4, 4)
Next
_GDIPlus_PathTransform($hPath, $hMatrix)
_GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen)


_GDIPlus_PenSetColor($hPen, 0xFF000000)
_GDIPlus_PathReset($hPath)
_GDIPlus_PathAddPolygon($hPath, $XY)
_GDIPlus_PathTransform($hPath, $hMatrix)

_GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen)

_GDIPlus_MatrixDispose($hMatrix)
_GDIPlus_PenDispose($hPen)
_GDIPlus_PathDispose($hPath)
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_Shutdown()

Do

Until GUIGetMsg() = -3

Even with simples vertice clouds, there are many possible variations, each of them being as "logical" or plausible than the others. Note that the section area is bigger in my example than the original I-beam, hence section area is not a valid criterion. Possible very dangerous structures could be built from most variants.


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

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

Share this post


Link to post
Share on other sites
9 hours ago, Chimp said:

tried to process the given points with the traveling salesman algorithm

That approach might work, but you'd have to adjust the cost functions to define the desired result as the optimum to be achieved. Off the top of my head  (without trying), I'd say, maybe impose additional cost conditions (for this particular case!) of every vertex angle being 90 degrees, and minimising total enclosed surface area. Defining appropriate cost functions is always the hardest part.;)

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

It would look something like this:D (with thanks to Chimp for the initial adaptation):

#include <Array.au3>
#include <GUIConstants.au3>
#include <GDIplus.au3>
#include <Math.au3>

Global Const $GUIwidth = 600
Global Const $GUIheight = 400
Global Const $citysize = 10
Global Const $halfcitysize = $citysize / 2

$hwnd = GUICreate("Straight-Angle Travelling Salesman Problem (using Simulated Annealing), by RTFC", $GUIwidth, $GUIheight)
GUISetState()

; Load GDI+ resources
_GDIPlus_Startup()
Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($GUIwidth, $GUIheight, $graphics)
Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)
Global $hPenLine = _GDIPlus_PenCreate(0xFF0000FF, 4)
Global $hPenCircle = _GDIPlus_PenCreate(0xFFFF0000, 4)

; Simulated Annealing vars
Global $temperat, $path, $kk, $nswap, $nswapstep, $cost, $tempstep, $absimp, $lowestcost

; initialise
SRandom(@MSEC + @AutoItPID); initialise randomising seed
$verbose = True ; T: write regular progress updates to console

; define cities
Global $XY[12][2] = [[0, 0],[15, 0],[15, 3],[0, 3],[6, 3],[9, 3],[9, 12],[6, 12],[0, 12],[15, 12],[15, 15],[0, 15]]
Global $ncity = UBound($XY) ; 20
Global $wrongAnglePenalty=10

Global $maxcity = $ncity * 50
Global $n[7], $xx[7], $yy[7] ; base-1 indexed
Global $x[$ncity + 1], $y[$ncity + 1], $iorder[$ncity + 1], $jorder[$maxcity + 1] ; base-1 indexed

;______START OF ANNEALING ROUTINE____________

$nover = 100 * $ncity ; maximum number of paths at any temperature
$nlimit = 10 * $ncity ; maximum number of successful path changes before continuing
$nwrite = Int($nover / 5) ; default status update interval if verbose=.t.
$tempsteps = 100 ; number of temperature steps to try
$tfactor = 0.90 ; annealing schedule: temperature is reduced by this factor after each step
$path = 0

While True
    $temperat = 0.5 ; initial temperature; smaller = more aggressive + more myopic search
    $absimp = 0 ; counter
    $nswapstepzero = 0 ; counter

    ; prep the buffers
    For $cc = 1 To 6
        $n[$cc] = 0
    Next

    For $cc = 0 To $ncity - 1
        $x[$cc] = 0.2 + $XY[$cc][0] * 0.020 ; Random()
        $y[$cc] = 0.2 + $XY[$cc][1] * 0.020 ; Random()
        $iorder[$cc] = $cc
        $jorder[$cc] = 0
    Next

    For $cc = $ncity + 1 To $maxcity
        $jorder[$cc] = 0
    Next

    ; prep the cost vars
    $path=_CalcPathLength()
    $prevpath=$path
    $initcost = $path
    $lowestcost = $path

    ; main loop starts here
    For $tempstep = 1 To $tempsteps ; try up to N temperature steps
        $nswap = 0
        $nswapstep = 0

        For $kk = 1 To $nover
            $n[1] = Random(1, $ncity, 1) ; choose beginning and end of segment
            $n[2] = Random(1, $ncity, 1)
            If $n[2] >= $n[1] Then $n[2] = 1 + Mod(($n[2] + 1), $ncity)

            ; count number of cities not on segment ($nn)
            $nn = 1 + Mod(($n[1] - $n[2] + $ncity - 1), $ncity)
            If $nn < 3 Then ContinueLoop

            ; store original situation
            $oldiorder=$iorder
            $oldjorder=$jorder

            ; decide whether to do a segment transport or reversal (equal chances)
            $doTransport = (Random() <= 0.5)
            If $doTransport Then ; try a segment transport
                $n[3] = $n[2] + Int(Abs($nn - 2) * Random()) + 1
                $n[3] = 1 + Mod($n[3] - 1, $ncity) ; transport to a location not on the path
                _DoTransport()
            Else
                _DoReversal()
            EndIf
            $cost=_CalcPathLength()-$prevpath

            ; Listen to the wind, talk to the trees...
            Switch _AskOracle()
                Case True

                    $nswap += 1
                    $path += $cost
                    $prevpath=$path

                    If $lowestcost > $path Then
                        $nswapstep += 1
                        $absimp += 1
                        $lowestcost = $path
                    EndIf

                    If $nswap >= $nlimit Then ExitLoop

                case Else   ;restore
                    $path=$prevpath
                    $iorder=$oldiorder
                    $jorder=$oldjorder
            EndSwitch
        Next

        If $verbose Then _ScreenOut()
        If $nswapstep = 0 Then $nswapstepzero += 1
        If $nswapstepzero = 30 Then ExitLoop ; no more improvements in the last N temperature steps

        ; reduce temperature = likelihood of following a trajectory away from the nearest LOCAL optimum (in the hope of getting nearer to the GLOBAL optimum)
        $temperat *= $tfactor
    Next

    ; show final result
    MsgBox($MB_OKCANCEL, "Simulated Annealing Test Result", "Shortest Path Length: " & $lowestcost)
    Exit

WEnd

_GDIclose()
Exit


Func _AskOracle()

    If $cost < 0 Then
        Return True
    Else ; this is where all the magic happens!
        Return (Random() < Exp(-($cost / $temperat)))
    EndIf

EndFunc   ;==>_AskOracle


Func _CalcPathLength()

    Local $path = 0
    Local $cc, $index1, $index2
    For $cc = 1 To $ncity - 1
        $index1 = $iorder[$cc]
        $index2 = $iorder[$cc + 1]
        $path += _Distance($x[$index1], $x[$index2], $y[$index1], $y[$index2])
    Next
    $index1 = $iorder[$ncity] ; close the loop by tying path ends together
    $index2 = $iorder[1]
    $path += _Distance($x[$index1], $x[$index2], $y[$index1], $y[$index2])

    For $cc = 1 To $ncity - 2
        $index1 = $iorder[$cc]
        $index2 = $iorder[$cc + 1]
        $index3 = $iorder[$cc + 2]

        Switch $x[$index1]=$x[$index2]
            case True
                Switch $y[$index1]<>$y[$index2]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch

            case Else
                Switch $y[$index1]=$y[$index2]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
        EndSwitch

        Switch $x[$index2]=$x[$index3]
            case True
                Switch $y[$index2]<>$y[$index3]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
            case Else
                Switch $y[$index2]=$y[$index3]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
        EndSwitch

        If $x[$index1]=$x[$index2] And $x[$index2]=$x[$index3] Then $path += $wrongAnglePenalty
        If $y[$index1]=$y[$index2] And $y[$index2]=$y[$index3] Then $path += $wrongAnglePenalty
    Next

    $index1 = $iorder[$ncity-1]
    $index2 = $iorder[$ncity]
    $index3 = $iorder[1]

        Switch $x[$index1]=$x[$index2]
            case True
                Switch $y[$index1]<>$y[$index2]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
            case Else
                Switch $y[$index1]=$y[$index2]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
        EndSwitch

        Switch $x[$index2]=$x[$index3]
            case True
                Switch $y[$index2]<>$y[$index3]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
            case Else
                Switch $y[$index2]=$y[$index3]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
        EndSwitch

        If $x[$index1]=$x[$index2] And $x[$index2]=$x[$index3] Then $path += $wrongAnglePenalty
        If $y[$index1]=$y[$index2] And $y[$index2]=$y[$index3] Then $path += $wrongAnglePenalty

    $index1 = $iorder[$ncity]
    $index2 = $iorder[1]
    $index3 = $iorder[2]

        Switch $x[$index1]=$x[$index2]
            case True
                Switch $y[$index1]<>$y[$index2]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
            case Else
                Switch $y[$index1]=$y[$index2]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
        EndSwitch

        Switch $x[$index2]=$x[$index3]
            case True
                Switch $y[$index2]<>$y[$index3]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
            case Else
                Switch $y[$index2]=$y[$index3]
                    case False
                        $path += $wrongAnglePenalty
                EndSwitch
        EndSwitch

        If $x[$index1]=$x[$index2] And $x[$index2]=$x[$index3] Then $path += $wrongAnglePenalty
        If $y[$index1]=$y[$index2] And $y[$index2]=$y[$index3] Then $path += $wrongAnglePenalty

    return $path
EndFunc   ;==>_CalcPathLength


Func _Distance($x1, $x2, $y1, $y2)

    Return Sqrt((($x1 - $x2) ^ 2) + (($y1 - $y2) ^ 2))
EndFunc   ;==>_Distance


Func _DoReversal()

    $n[3]=1+Mod(($n[1]+$ncity-2),$ncity)    ; find the city before n[1]...
    $n[4]=1+Mod($n[2],$ncity)               ; and after n[2]

    ; find coordinates of the four cities
    local $ii,$jj,$dex
    For $jj=1 to 4
        $dex=$n[$jj]
        $ii=$iorder[$dex]
        $xx[$jj]=$x[$ii]
        $yy[$jj]=$y[$ii]
    Next


    Local $mm = (1 + Mod(($n[2] - $n[1] + $ncity), $ncity)) * .5
    Local $ii, $jj, $ll, $itmp
    For $jj = 1 To $mm
        $ii = 1 + Mod(($n[1] + $jj - 2), $ncity)
        $ll = 1 + Mod(($n[2] - $jj + $ncity), $ncity)

        $itmp = $iorder[$ii]
        $iorder[$ii] = $iorder[$ll]
        $iorder[$ll] = $itmp
    Next

EndFunc   ;==>_DoReversal


Func _DoTransport()

    $n[4]=1+Mod($n[3],$ncity)               ; find the city following n[3]
    $n[5]=1+Mod(($n[1]+$ncity-2),$ncity)    ; find the city before n[1]...
    $n[6]=1+Mod($n[2],$ncity)               ; and after n[2]

    ; find coordinates of the six cities
    local $jj,$dex
    For $jj=1 to 6
        $dex=$n[$jj]
        $ii=$iorder[$dex]
        $xx[$jj]=$x[$ii]
        $yy[$jj]=$y[$ii]
    Next

    Local $m1, $m2, $m3, $pp
    $m1 = 1 + Mod(($n[2] - $n[1] + $ncity), $ncity) ; find # cities from n1->n2
    $m2 = 1 + Mod(($n[5] - $n[4] + $ncity), $ncity) ; find # cities from n4->n5
    $m3 = 1 + Mod(($n[3] - $n[6] + $ncity), $ncity) ; find # cities from n6->n3

    Local $mm = 1
    For $pp = 1 To $m1
        $jj = 1 + Mod($pp + $n[1] - 2, $ncity)
        $jorder[$mm] = $iorder[$jj]
        $mm += 1
    Next

    For $pp = 1 To $m2
        $jj = 1 + Mod($pp + $n[4] - 2, $ncity)
        $jorder[$mm] = $iorder[$jj]
        $mm += 1
    Next

    For $pp = 1 To $m3
        $jj = 1 + Mod($pp + $n[6] - 2, $ncity)
        $jorder[$mm] = $iorder[$jj]
        $mm += 1
    Next

    For $pp = 1 To $ncity
        $iorder[$pp] = $jorder[$pp]
    Next

EndFunc   ;==>_DoTransport


Func _ScreenOut()

    ConsoleWrite("Simulated Annealing. Initial Path length: " & $initcost & @CRLF)
    ConsoleWrite("Step: " & $tempstep & " of " & $tempsteps & "; Temperature: " & $temperat & @CRLF)
    ConsoleWrite("Executed Swaps: " & $nswap & "; shortest Path length: " & $lowestcost & @CRLF)
    ConsoleWrite("Total Improvements: " & $absimp & "; Improvements this step: " & $nswapstep & @CRLF & @CRLF)
    _DrawTSroute()

EndFunc   ;==>_ScreenOut


Func _DrawTSroute()

    _GDIPlus_GraphicsClear($backbuffer)

    For $cc = 1 To $ncity - 1
        $index1 = $iorder[$cc]
        $index2 = $iorder[$cc + 1]
        _DrawLine($x[$index1], $x[$index2], $y[$index1], $y[$index2])
    Next
    $index1 = $iorder[$ncity] ; close the loop by tying path ends together
    $index2 = $iorder[1]
    _DrawLine($x[$index1], $x[$index2], $y[$index1], $y[$index2])
    _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $GUIwidth, $GUIheight)

EndFunc   ;==>_DrawTSroute


Func _DrawLine($x1, $x2, $y1, $y2)

    Local $x1scaled = Round($GUIwidth * $x1, 0)
    Local $y1scaled = Round($GUIheight * $y1, 0)
    Local $x2scaled = Round($GUIwidth * $x2, 0)
    Local $y2scaled = Round($GUIheight * $y2, 0)

    _GDIPlus_GraphicsDrawArc($backbuffer, $x1scaled - $halfcitysize, $y1scaled - $halfcitysize, $citysize, $citysize, 0, 360, $hPenCircle)
    _GDIPlus_GraphicsDrawLine($backbuffer, $x1scaled, $y1scaled, $x2scaled, $y2scaled, $hPenLine)

EndFunc   ;==>_DrawLine


Func _GDIclose()

    _GDIPlus_PenDispose($hPenLine)
    _GDIPlus_PenDispose($hPenCircle)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()

EndFunc   ;==>_GDIclose

Of course, the new cost function as crudely implemented here is favouring right angles and non-overlapping line segments as additional constraints (through var $wrongAnglePenalty). A more general solution to close polygons would need more sophisticated cost functions. The problem is how to define a generic optimal solution; that'll still depend on your specific requirements. So this specific solution won't work for angles other than 90/270 degrees, for example.

Edited by RTFC
typo
1 person likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

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

Create an account

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


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now