1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Mars

Beiträge von Mars

  • Unterstützung für AutoIT Script

    • Mars
    • 13. März 2021 um 03:13

    Der Trick sind Arrays. Du hast unmengen an redundanten Daten in deinem Programmcode. Immer wenn ein Ablauf nur von verschiedenen Daten, aber nicht von verschiedener "Struktur" abhängt, kann man Arrays nutzen. (z.B. du hast ein Label und willst dort 10 verschiedene Strings anzeigen lassen je nachdem was man anklickt. Dann speicherst du diese 10 Strings in einer Liste und benutzt z.B. Liste[0] um den ersten String zu bekommen).

    Trick Nummer 2 sind MEHR ARRAYS :D

    Wenn du einen Datensatz hast (bestehend aus Titel, OS, CPU, GPU, ... etc) ist dieser ein Array. Wenn du viele Datensätze hast, ist das ein Array welches Arrays enthält.

    Trick Nummer 3: Generalisierung im Allgemeinen

    Immer wenn man in der Programmierung eine Anzahl Probleme (z.B. der große ElseIf Teil, oder eine eigene Funktion für jedes Spiel LOL(), GTA(), ...()) hat, die sich sehr ähnlich sind, versucht man einen Schritt zurückzutreten und "alle" Probleme dieses Typs gleichzeitig zu lösen. Was passiert, wenn du ein Spiel hinzufügen willst? Im Optimalfall ergänzt du in einer Liste ein paar Zeilen und fertig, aber du möchtest keine neuen Funktionen schreiben, keine neuen GUIs erstellen, keine neuen Ctrls erstellen, etc.

    Das klingt jetzt als würde ich dich angreifen, will ich aber wirklich nicht. Das sind alles Tips :thumbup:

    Man wächst an seinen Aufgaben, und einfache Programme sind super geeignet um etwas zu lernen ;)

    Anbei gibt es auch gleich ein Grundgerüst für "eine" Lösung des Problems (es gibt immer sehr viele verschiedene richtige Wege ein Problem zu lösen, hier wird nur "einer" gezeigt. Jeder hat einen eigenen Programmierstil). Das UserInterface (GUI) ist selbstverständlich nicht ausgereift, ich habe auch nicht alle Spiele hinzugefügt und der Text der angezeigt wird ist nicht schön formatiert, vielleicht sind auch noch Bugs drin, habe das jetzt nicht 5 Stunden getestet. Das sind alles Sachen an denen du dich austoben kannst 8o

    AutoIt
    ; Yo
    
    Global $aaInfo[4] ; aaInfo steht für Array of aInfo, also eine Liste die Arrays mit Infos enthält. Verschachteltes Array.
    ; Wenn du mehr als 4 Spiele unterstützen willst hier aus der [4] irgendwas höheres machen sodass es zur Anzahl Spiele passt.
    For $i = 0 To UBound($aaInfo) - 1 Step 1
        $aaInfo[$i] = InfoCreate()
    Next
    
    ; Das habe ich hier extra so aufgebaut, damit man die Info später einfacher aus einer Ini holen kann wenn man will.
    InfoSet($aaInfo[0], 'Titel'         , 'CS:GO')
    InfoSet($aaInfo[0], 'Betriebssystem', 'Windows 7/Vista/XP')
    InfoSet($aaInfo[0], 'CPU'           , 'Intel CoreTM 2 Duo E6600 or AMD PhenomTM X3 8750')
    InfoSet($aaInfo[0], 'RAM'           , '2 GB')
    InfoSet($aaInfo[0], 'Grafik'        , 'Die Grafikkarte muss mindestens 256 MB haben und sollte mit DirectX 9 Kompatibel sein, und Pixel Schader 3.0 unterstützen.')
    InfoSet($aaInfo[0], 'DirectX'       , 'Version 9.0c')
    InfoSet($aaInfo[0], 'Festplatte'    , '15 GB')
    
    InfoSet($aaInfo[1], 'Titel'         , 'League of Legends')
    InfoSet($aaInfo[1], 'Betriebssystem', 'Windows XP')
    InfoSet($aaInfo[1], 'CPU'           , '2 GHz Prozessor')
    InfoSet($aaInfo[1], 'RAM'           , '1 GB')
    InfoSet($aaInfo[1], 'Grafik'        , 'Shader version 2.0 & DirectX capable video card.')
    InfoSet($aaInfo[1], 'DirectX'       , 'Version 9.0c')
    InfoSet($aaInfo[1], 'Festplatte'    , '12 GB')
    
    InfoSet($aaInfo[2], 'Titel'         , 'irgendein Spiel')
    InfoSet($aaInfo[2], 'Betriebssystem', 'Windows 95+')
    InfoSet($aaInfo[2], 'CPU'           , '7 GHz Prozessor')
    InfoSet($aaInfo[2], 'RAM'           , '100 GB')
    InfoSet($aaInfo[2], 'Grafik'        , 'Shader version 31.41 & 2TB GDDR8')
    InfoSet($aaInfo[2], 'DirectX'       , 'Version 15.0c')
    InfoSet($aaInfo[2], 'Festplatte'    , '77 TB')
    
    InfoSet($aaInfo[3], 'Titel'         , 'irgendein Spiel (teil 3)')
    InfoSet($aaInfo[3], 'Betriebssystem', 'Windows 94+')
    InfoSet($aaInfo[3], 'CPU'           , '9 GHz Prozessor')
    InfoSet($aaInfo[3], 'RAM'           , '100 TB')
    InfoSet($aaInfo[3], 'Grafik'        , 'Shader version 31.415 & 17TB GDDR0')
    InfoSet($aaInfo[3], 'DirectX'       , 'Version 19.0c')
    InfoSet($aaInfo[3], 'Festplatte'    , '12345 TB')
    
    ; Hier kann man einfach weitere sachen hinzufügen, die sind dann automatisch drin.
    
    
    ; Das UserInterface sah so lustiger aus. Aber das kann jeder so gestalten wie man will.
    Global $iW = 320, $iH = 260
    Global $hGUI = GUICreate('Ich bin ein Fenster', $iW, $iH)
    Global $hDDM = GUICtrlCreateCombo(($aaInfo[0])[0][1], 10, 10, 150, 25) ; Ja man kann verschachtelte Arrays via (aaList[0])[...] ansprechen. Ist nicht sehr performant, ist hier aber egal.
    For $i = 1 To UBound($aaInfo) - 1 Step 1
        GUICtrlSetData($hDDM, ($aaInfo[$i])[0][1])
    Next
    Global $hBTN = GUICtrlCreateButton('Lets Go', 170, 10, 100, 25)
    Global $hEDT = GUICtrlCreateEdit('Info', 10, 50, 300, 200, 0, 2048)
    GUICtrlSetBkColor($hEDT, 0x404040)
    GUICtrlSetFont($hEDT, 11, 400, 0, 'Consolas', 5) ; Wenn Consolas nicht installiert ist einfach Arial hier hinschreiben.
    GUICtrlSetColor($hEDT, 0x40EE80)
    GUISetBkColor(0x202020, $hGUI)
    GUISetState(@SW_SHOW, $hGUI)
    
    
    While True
        Switch GUIGetMsg()
            Case -3
                Exit
            Case $hBTN
                Local $sRW = GUICtrlRead($hDDM)
                ; In hDDM ist jetzt ein String = Spielname. Der ist auch in (aaInfo[i])[0][1].
                For $i = 0 To UBound($aaInfo) - 1 Step 1
                    If ($aaInfo[$i])[0][1] = $sRW Then
                        $sRW = ''
                        For $ii = 0 To UBound($aaInfo[$i]) - 1 Step 1
                            $sRW &= ($aaInfo[$i])[$ii][0] & ': ' & ($aaInfo[$i])[$ii][1] & @CRLF
                        Next
                        GUICtrlSetData($hEDT, $sRW)
                        ExitLoop
                    EndIf
                Next
        EndSwitch
    WEnd
    
    Func InfoCreate()
        Local $aInfo[7][2] ; Wenn mehr Keys dazukommen, hier aus [6][2] ein [7][2] oder mehr machen.
        $aInfo[0][0] = 'Titel'
        $aInfo[1][0] = 'Betriebssystem'
        $aInfo[2][0] = 'CPU'
        $aInfo[3][0] = 'RAM'
        $aInfo[4][0] = 'Grafikkarte'
        $aInfo[5][0] = 'DirectX'
        $aInfo[6][0] = 'Festplatte'
        Return $aInfo
    EndFunc
    
    Func InfoSet(ByRef $aInfo, $sKey, $sValue)
        For $i = 0 To UBound($aInfo) - 1 Step 1
            If StringLeft($aInfo[$i][0], StringLen($sKey)) = $sKey Then ; Lineare Suche (reicht bei wenigen Keys), partial Match geht, also z.B. "Grafik" statt "Grafikkarte" schreiben.
                $aInfo[$i][1] = $sValue
                ExitLoop
            EndIf
        Next
    EndFunc
    
    Func InfoGet(ByRef $aInfo, $sKey)
        For $i = 0 To UBound($aInfo) - 1 Step 1
            If StringLeft($aInfo[$i][0], StringLen($sKey)) = $sKey Then Return $aInfo[$i][1]
        Next
    EndFunc
    Alles anzeigen

    lg

    M

  • Raspberry Pi AutoIT

    • Mars
    • 28. Januar 2021 um 15:27

    1. Was willst du machen?

    2. Welche Hardware ist dafür geeignet?

    3. Welche Sprache benötige ich zur Programmierung?

    zu 2. Wenn eine Antwort Arduino ist: Dafür gibt es so viele Tutorials und eine unfassbar einfache (aber primitive) IDE (Damit kann man nichts falsch machen (und auch nichts richtig), das hier hätte ich anders formulieren müssen :D), dass du hier mit an Sicherheit grenzender Wahrscheinlichkeit besser aufgehoben bist als bei AutoIt, denn AutoIt ist primär zur Automatisierung von auf Windows laufenden Programmen geplant gewesen. Natürlich hat die Zeit und die vielen UDFs diese Sprache zu etwas ganz anderem werden lassen, aber das Verhalten eines Arduino mit AutoIt via Windows auf einem PI zu realisieren ist wesentlich komplizierter als direkt einen Arduino zu nutzen.

    Also beantworte wenigstens die erste der 3 Fragen, damit kann man schonmal mehr anfangen als mit 0 Antworten.

  • Corona - endlich impfen

    • Mars
    • 8. Januar 2021 um 20:20

    Immer alle über einen Kamm scheren ist auch nicht soooo gut.
    Ich möchte mich z.B. nicht impfen lassen, weil die Kombination aus wenig Kontakt & auf dem Land leben & sehr selten Einkaufen mich nicht unbedingt zu den gefährdesten Leuten zählen lässt. Weiterhin vertraue ich keinem Impfstoff den es vor einem Jahr noch nicht gab, natürlich wurde alles anständig geprüft, aber wie bei Zigaretten, den Krebs bekommt man erst in 20 Jahren, wer weiß was da noch so passiert.

    Zusätzlich gibt es tonnenweise Leute (die mehr Kontakt zu Menschen haben) die es wichtiger brauchen als ich.

    also Abwarten & Tee trinken.

  • Rectangular Decomposition of Images

    • Mars
    • 6. Januar 2021 um 19:03

    Moin,

    Nachdem das Thema kurz in der Shoutbox aufgetaucht ist und ich einige gute Hinweise bekommen habe wie man ein solches Problem angehen könnte, habe ich mich hingesetzt und eine (mehr oder minder) funktionierende Lösung gebastelt.

    Was kann das Skript:

    Es zerlegt Bilder in einfarbige Rechtecke die in einer gewissen Reihenfolge übereinandergestapelt werden und im Endeffekt eine verlustfreie Repräsentation des Bildes liefern.

    Vorgehensweise:

    1. Zähle die Farben im Bild

    2. Erstelle für jede Farbe eine "bit"Map (also ein 2D Array aus 0 und 1) in derselben Größe wie das Bild (ab hier Layer genannt).

    3. Erstelle aus den Layern eine 012Map (0 = darf nicht überzeichnet werden, 1 = darf überzeichnet werden, 2 = MUSS überzeichnet werden) für jede Farbe.

    4. Erstelle aus jeder 012Map eine möglichst minimale Dekomposition

    5. Stapel nun alle Dekompisitionen (jeweils korrekt gefärbt) übereinander et voilà, das Originalbild entsteht wie durch Zauberhand.

    Das Problem ist nicht die Vorgehensweise ansich, sondern, dass es viele Schritte gibt die keine "schnellen" Lösungsalgorithmen erlauben, oder Schritte bei denen man eine Lösung nicht auf Optimalität prüfen kann ohne alles durchzuprobieren (brute Force).


    Schritt 3: Layer pro Farbe -> 012Map pro Farbe

    - Klingt als könnte hier nichts schiefgehen, aber welche Reihenfolge der Layer ist denn nun optimal?

    - Bei einem 8 Farben Bild wären das schon 8! = ca. 40.000 Möglichkeiten, die will man nicht alle durchprobieren.

    - Zur Optimierung wird hier eine Startlösung verwendet und immer wieder 2 Layer vertauscht, wenn das etwas bringt -> weiter, wenn nicht -> zurücktauschen.

    Schritt 4: Dekomposition der 012Map

    - Es gibt oft keine eindeutige Lösung, das ist super, weil es reicht "eine" optimale Lösung zu finden, aber woher weiß man ob die Lösung optimal ist?

    - Wird durch glorifiziertes Ausprobieren gelöst (genau wie der vorherige Teil)

    Die Methode ist relativ langsam (vllt in C++ umschreiben, aber dafür bin ich jetzt zu faul), für kleine Sprites mit wenigen Farben ist sie aber nützlich ;)

    Da ich nicht nochmal 50 Seiten schreiben will (das Skript zum Programm hat ja schon einige wenige Zeilen) gibt es hier einfach das Skript zum Ausprobieren. Wenn Fehler/Fragen/Anregungen/etc. auftauchen, her damit :thumbup:

    PS: Es ist Absicht, dass Layerweise gearbeitet wird (also 1 Layer/Farbe) und die Rechtecke nicht vollkommen z-Unabhängig sind, so kann man "1x Farbe setzen -> 10 Rechtecke Zeichnen, 1x Farbe setzen -> xyz Rechtecke Zeichnen" und muss nicht für jedes Rechteck den Farbwert einzeln speichern (obwohl er der Einfachheithalber angehängt wurde)

    lg

    M

    Dateien

    ImageDecompose.zip 32,47 kB – 714 Downloads
  • Mindustry Logic Compiler

    • Mars
    • 1. Januar 2021 um 16:07

    Moin,

    Eine (offizielle) Einleitung zum Thema gibts hier: Mindustry Logic 6.0 Reddit

    Einführung

    Ich weiß nicht wie viele Leute es hier gibt die Mindustry spielen, aber der ein oder andere wird es vermutlich sein ;)

    Mit Mindustry 6.0 wurden Logikprozessoren eingeführt, das sind Gebäude die mit einer gewissen Geschwindigkeit (z.B. 120 Instruktionen/Sekunde) eine Assemblerähnliche Sprache ausführen. Diese Sprache bietet die Möglichkeit viele Objekte im Spiel zu kontrollieren:

    - Ein Lager soll immer den Rohstoff der am häufigsten drin ist ausgeben, oder abwechselnd 2 Rohstoffe, und das alles aus demselben Entlader.

    - Auf einem Display (auch ein Gebäude im Spiel) will jemand unbedingt Snake/Tetris/Pacman/Paddlewar/etc. spielen.

    - In einer Nachricht (ein Gebäude im Spiel das Text anzeigt) steht wie viele Rohstoffe rein- und rausgehen.

    - Auf einem Display wird dieselbe Info aus der obigen Zeile grafisch als Balkendiagramm + Farbe + Icons angezeigt

    - Jemand will unbedingt Primzahlen ausrechnen.

    - usw usw. Es gibt unzählige Sachen die man tun kann.

    Der Rückschlag für jeden Programmierer kommt aber sofort mitgeliefert: Die ASM-Ähnliche Sprache ist extrem "klein". Es gibt ausschließlich eine einzige Instruktion zur Flussregelung, JumpIf. Diese akzeptiert zusätzlich ausschließlich Dezimalzahlen als Sprungadresse:

    - JumpIf a < 5 to 5 (Springt zu Zeile 5, wenn a < 5, die echte Syntax ist: "jump 5 lessThan a 5")

    Das ist wahrlich nicht schon zu lesen, oder zu schreiben. Zusätzlich gibt es keine Labels (also ich kann nicht "JumpIf a < 5 To #label" schreiben, und wer schonmal programmiert hat weiß, dass sich Zeilennummern andauernd ändern, wenn man etwas oberhalb entfernt oder einfügt). Edit: Inzwischen gibt es im ASM Labels, die beim Import (zu int) resolved werden (sie können also nicht wieder exportiert werden)

    Also habe ich vor einigen Tagen angefangen einen Compiler zu schreiben, um zumindest die grundliegende Funktionalität die man zum Programmieren braucht bereitzustellen. (da ich keine Ahnung im Compilerbau habe habe ich mir alles selbst ausgedacht, falls jemand sich damit auskennt: Code lesen auf eigene Gefahr, vermutlich werden die Haare zu Berge stehen ^^)

    Version 0.1

    Was geht:

    - Syntax vollständig befreit von Whitespaces, alles wird über Klammern und Zeilenumbrüche geregelt -> If (a < 5) goto (5)

    - Übersetzung sämtlicher Arithmetik und aller Builtin Funktionen die von der Sprache unterstützt werden (außer Units und Radar, was das genau macht und wie man es verwendet weiß ich noch nicht, habe ich nicht getestet und dementsprechend nicht implementiert)

    - Einführung von Labels (beginnen mit #) & Labelarithmetik (vereinfacht, es gehen Sachen wie goto(#label+2), ausschließlich mit "+" und "-")

    - Sämtliche JumpIf Variationen sind gewrappt und ergeben sowas wie If (a = 5) goto (#label)

    - Einführung von If

    - Einführung von For (in einer Kombi aus C++ und AutoIt Syntax, For (i = 0; i < 4; i++) ... Next, das war mit Abstand am einfachsten und es lässt sich auch gut schreiben. Die Semikolons nerven ggf manche Leute, man kann stellvertretend auch "," nutzen, in Zukunft soll aber auch Inlinen möglich sein, sodass For (i = MyFunc(1, 2); i < 5; i++) mehr Kommas besitzt und das Zerlegen wieder komplizierter wird, deshalb bleibt es zumindest vorerst bei Semikolons.

    - Eingie Syntax ist redundant (z.B. kann man == oder = verwenden, und <> oder !=)

    - Einige Syntax ist doof (z.B. beinhaltet die ASM-Sprache "idiv", was durch "//" symbolisiert werden müsste, das ist aber bereits für Kommentare reserviert, also wird "/%" = "idiv", oder "pow" sollte eigentlich durch "^" gekennzeichnet werden, das ist aber schon BitXOR, also wird hier "**" verwendet)

    Was nicht geht:

    - Sämtliche Verkettungen (a = Sqrt(a + b)), JEDE Operation muss nacheinander einzeln ausgeführt werden. Es gibt lustigerweise in der ASM Sprache Sachen wie a = Sqrt(b^2+c^2), manches lässt sich also umformen um operationen einzusparen

    - Die original Syntax basiert auf Leerzeichen zur Argumententrennung, außerdem enthält sie oft ungenutzte Argumente (z.B. "draw color r g b a 0 0", die Nullen am Ende). Sie wird als Input nicht unterstützt.

    - Vermutlich eine ganze Menge die ich nur noch nicht kenne ;)

    Version 0.2

    - Vollständig umgeschrieben (sollte nun seltener crashen)

    - If else endif

    - For syntax changed -> For (i = 0, i < 9, i++). Jetzt mit Kommas statt Semikolons

    - Kommentare werden jetzt mit ; statt mit // eingeleietet

    - Inteverdivision // statt /%

    - Exponent ^ statt **

    - Parameter und Returnlose Subroutines (Ist quasi nicht mehr und nicht weniger als "ein Stück Code auslagern")

    - Konstanten Hinzugefügt: SIZE_CELL = 64, SIZE_BIGCELL = 512, SIZE_DISPLAY = 80, SIZE_BIGDISPLAY = 176

    - Loop EndLoop (einfach eine Schleife ohne Zähler die unendlich weiterläuft)

    - Random() und Random(min, max) hinzugefügt

    - Arrays (benötigen eine Speicherzelle) hinzugefügt. Syntay ist typisches array[index] = var, und var = array[index].

    - IDE: Umsortiert, Beispiel für "Ball" und "DumpCell" hinzugefügt. ("Bricks" ist nicht fertig geworden)

    - IDE: Output der verschiedenen Compilestages jetzt einsehbar (falls was schiefgeht sieht man besser "wo")

    - IDE: Laden und Speichern hinzugefügt (naja.... IDE sollte man dieses schrecklich designte Fenster nicht nennen)

    Trivia

    Ich habe bisher kaum Programme geschrieben und ausprobiert, weil ich die Priorität darauf gesetzt habe, dass die Grundlagen erstmal funktionieren, Testen und Bugs Fixen ist also noch nicht weit fortgeschritten, wenn ihr das Programm verwendet wird es zu 100% irgendwelche Crashes geben (dabei geht auch der Code verloren, ab und zu in ein Textdokument kopieren hilft). In diesen Fällen bitte unbedingt hier im Thread das Beispielprogramm welches den Crash verursacht posten, dann schaue ich mir das an, eigentlich sollte es wenn überhaupt Errormeldungen geben und keine Crashes.

    Außerdem ist das UI extrem rudimentär (da kenne ich mich nicht gut aus, vielleicht will ja irgendjemand etwas basteln :)), hauptsache war dass es "geht".

    Es gibt von meiner Seite aus auch keine vollständige Erklärung zum Sprachumfang, um zu wissen was alles geht und was nicht geht bitte hier nachschlagen:

    Selbstverständlich muss man mit der ganzen Sache erstmal warm werden bevor man anfängt großartige Programme zu schreiben. Für Leute die etwas grafisches machen wollen empfehle ich einen Blick in die "draw" Befehle. PS: Sämtliche Print und Draw Befehle laufen in einen Puffer, via drawflush und printflush kopiert man diesen Puffer ins jeweilige Gebäude (Message oder Display).

    Außerdem ist es wissenswert, dass ALLE Variablen im globalen Scope liegen und static sind. Bei jedem Durchlauf des Programms haben die Variablen zu Beginn also die Werte die sie zuletzt bei Programmende hatten. Das lässt sich via "exit" (bzw. "end" in der ASM-Sprache) im Code resetten.

    Mini Tutorial

    So genug der langen Rede, hier ein kleines Tutorial mit dem einzigen Programm das ich bisher geschrieben habe:

    unnamed.png

    [1]: Hier schreibt man seinen Programmcode hinein

    [2]: Hier kommt das was man in Mindustry verwenden kann heraus

    [3]: Hier kommen Errormeldungen heraus

    [4]: Hier gibt es (aktuell genau 1) Beispiele für Programmcode [5]: Das ist der Compile Button (F5 geht auch)

    unnamed.png

    [1]: Nachrichtenblock (den verknüpft man indem man zuerst auf den Prozessor und dann auf den Nachrichtenblock klickt)

    [2]: Mikroprozessor (hier klickt man auf das Symbol unter dem Gebäude um den Code zu bearbeiten)

    unnamed.png

    Im Menu des Prozessors klickt man unten in der Mitte auf bearbeiten. Anschließend kann man seinen Code importieren.

    unnamed.png

    Das sieht dann in etwa so aus. Wenn man dieses Menu via "Zurück" verlässt fängt der Prozessor an zu arbeiten, da er nur 120 Instruktionen/Sek schafft dauert es ein paar Sekunden (ca. 10) bis die Berechnung fertig ist.

    unnamed.png

    So sieht das Endergebnis dann aus.

    Das Programm gibts im Anhang.

    Hinweis: In Post#5 ist eine ausführliche Dokumentation.

    lg

    Mars

    Downloads:

    - v0.1: 291

    - v0.2: current

    Dateien

    Mindustry Logic Compiler v0.2.zip 27,16 kB – 340 Downloads
  • [Python] Neural Network

    • Mars
    • 12. Dezember 2020 um 20:51

    Moin,

    leider bin ich wirklich nicht fit in Python, ein MultilayerNN habe ich dort aber (from scratch) schonmal implementiert (war eine Hausaufgabe, da muss man wohl oder übel durch :D). Leider habe ich wie gesagt von Python keinen Dunst und daher meine Inspiration aus youtube gezogen:

    - relativ theoretisch (aber sehr einfach erklärt) wie man ein NN baut: 3B1B

    - Python NN (nur der Anfang, in den Links/Kommentaren ist aber ein fertiges was funktioniert): SL

    Ich bin mir fast sicher, dass du die Videos bereits kennst, aber falls nicht hilft dir das möglicherweise. So wie ich das sehe bist du mit einem simplen NN (und z.B. Sigmoid + ((8), 13, 7, 3, (1)) das du selbst gebastelt hast besser bedient, als wenn du mit Kanonen auf Spatzen schießt (pytorch). Dann verstehst du auch woher jeder Wert kommt, wie alles zustandegebracht wurde etc. Ggf fällt dir dann eine Methode ein wie du dein selbst gebasteltes NN an die Bedingungen die du hast anpassen kannst.

    Ein paar Tips:

    - Skaliere deinen Input/Output immer zwischen 0 und 1 (oder -1 bis 1, je nach Aktivierungsfunktion), da ist die Ableitung der Aktivierungsfunktion am brauchbarsten.

    - Größere Netze brauchen viele Trainingsdaten, wenn man ihnen zu wenige gibt "lernen" sie die Daten und nicht das Prinzip dahinter

    - (vorallem) Kleine Netze fressen sich manchmal auf unbestimmte Zeit fest. Danach verbessern sie sich um einen unvorhersehbaren Betrag. Es ist ziemlich schwierig (bzw. ich wüsste keinen Ansatz dazu) nach einer festgelegten Zeit T herauszufinden welches Modell "gut" ist und welches "schlecht" ist. Man kann sehr grob aussortieren (ggf. die "schlechtesten" 50% ausschließen), das ist aber keine Garantie dafür, dass die "besseren" 50% auf lange Sicht "gut" bleiben.

    Es tut mir leid, dass ich nicht wirklich konkret helfen kann, vielleicht konnte ich aber einen Anstoß bieten, dann hat sich dieser Beitrag bereits gelohnt. Neurale Netze sind nicht unbedingt das am besten abgedeckte Fachgebiet hier im Forum :D

    lg

    M

  • Verhindern, dass Fenster Größe ändert bei Ziehen an Bildschirmrand

    • Mars
    • 7. November 2020 um 14:40

    Ich weiß nicht ob das Hilft, aber bei Fenstern "selbstgebauter Titelleiste" (also z.B. Labels mit NCHITTEST zum Bewegen, eigene Buttons, etc) passiert keines dieser Events (allerdings werden wahrscheinlich auch nützliche Events verschluckt).

    Falls dein Fenster also keine Menuzeile hat (die ist sonst ganz oben, wobeeeeei, die kann man doch bestimmt als Pseudotitelleiste missbrauchen, wenn man ihren Grafikpuffer geschickt übermalt :D), kannst du via WS_POPUP ein "nacktes" Fenster erzeugen und die von dir gewünschten zulässigen Events (Resize wenn der User es will, Minimieren, Maximieren, Exit, Verschieben, etc) manuell verarbeiten.

    Kann gut sein, dass das viel zu viel arbeit ist, ist nur eine Überlegung :)

    lg

    M

  • Im Internet jumpen

    • Mars
    • 1. November 2020 um 15:22

    Ja das ist ärgerlich, heutzutage wird so viel über Skripte dynamisch nachgeladen, dass man kaum noch an alle Infos kommt wenn man "nur den Quellcode" hat.

    Im Prinzip ist der "richtige" Weg grundsätzlich NICHT im Browser irgendetwas per Maus anzuklicken, sondern so weit es geht nur Text zu verarbeiten bis man ans Ziel kommt. Hast du mal versucht die Webseite mit einem Textbasierten Browser zu öffnen? Das ist ggf. auch nicht super, aber vielleicht findet so ein Browser (der üblicherweise auch sehr schnell und leichtgewichtig ist) deinen Text auch ohne Mousehover (je nach nachlademethode und je nach Textbrowser).

    Da ich mich mit Webseiten usw. nicht auskenne kann ich nicht wirklich helfen. Die idee mit dem Textbrowser kam mir spontan, vielleicht ist die auch Unfug, Versuch macht Klug :)

    lg

    M

  • Was ein Mist!!

    • Mars
    • 5. Oktober 2020 um 23:33

    Sowas ähnliches ist mir auch schonmal passiert. Da hing es aber nicht mit AutoIt zusammen, sondern mit irgendeiner anderen Seite (kann mich nicht mehr erinnern). Hatte einen riesen Beitrag geschrieben und anschließend ausversehen die eine seitliche Maustaste meiner Maus gedrückt die dem "Zurück Button" entspricht, sodass ich auf die vorherige Seite zurückgeleitet wurde. Alles futsch...

    Seitdem schreibe ich alles wichtige in Word (online) oder einem beliebigen anderen Onlinedienst (z.B. auch Google Docs) vor, da speichert es automatisch jede Änderung ohne mein Zutun und wenn ich ausversehen die Seite zumache, der Strom ausfällt oder irgendwas anderes dummes passiert ist alles geschriebene noch da.

    Blöde Sachen passieren hin und wieder, da ist niemand wirklich sicher ;(

    lg

    M

  • Button in Programmschleife richtig abfragen !?!?

    • Mars
    • 2. Oktober 2020 um 16:03

    Ein kleiner Tip zum EventMode: Wenn du keine Lust hast für jeden Button eine eigene Funktion zu schreiben kann man auch eine übergeordnete Funktion für alle Buttons (z.B. "Gui_Button_Event") registrieren und innerhalb dieser Funktion via "Switch @GUI_CtrlId" bestimmen welches Ctrl man verwalten möchte (und dann die Aktionen aus Gui_button_start/stop ausführen). Das ist manchmal sinnvoll wenn man den Überblick behalten will und die Funktionen allesamt sehr klein sind, sodass es sich nicht lohnt 20 Einzeiler-Funktionen zu haben. Aber das entscheidet im Endeffekt jeder für sich selbst :)

    lg

    M

  • Fuzzy-Search

    • Mars
    • 2. Oktober 2020 um 15:45

    Hah, das ist ja super ^^

    Da fühle ich mich gleich schlecht, dass ich soetwas ähnliches in der SB nachgefragt habe, ich wollte damit nicht veranlassen, dass mir jemand die Arbeit abnimmt, sondern nur nachfragen ob es sowas gibt :S

    Vielen Dank ;)

    lg

    M

  • File zu array - mit unterschiedliche daten

    • Mars
    • 16. September 2020 um 17:56

    Vor langer Zeit habe ich mal eine Funktion gebastelt die einen String -> Array verwandelt (und umgekehrt). Dabei wird (nahezu) jeder Datentyp unterstützt. Man kann also z.B. ein Array aus Arrays vom Typ [String, float, int, Filepath, int int] haben und daraus einen einzelnen String machen, bei der rückumwandlung werden die Datentypen auch wiederhergestellt (also es ist nicht alles "String", sondern ehemalige ints bleiben ints).

    Ich weiß nicht genau was du vorhast, aber ich selbst nutze diese Funktion ziemlich oft um Sachen auf der Festplatte zwischenzuspeichern. Dann hat man im Skript ein großes Array das alles relevante enthält und dieses schreibt und liest man bei Bedarf auf die Platte. Der hierbei entstehende String ist aber NICHT für Menschen nachvollziehbar, man kann also nicht von Hand darin herumschreiben.

    _ArrayToStringEx

    lg

    M

  • Spielt ihr Online Spiele?

    • Mars
    • 14. September 2020 um 19:35

    WC3 Burbenog TD = Map mit den meisten Spielstunden bei mir. ich glaube die hab ich schon 100+ Mal gespielt mit Freunden ^^

  • Spielt ihr Online Spiele?

    • Mars
    • 13. September 2020 um 21:30

    League of Legends (aber nur aus Spaß, kein Ranked Spieler)
    Mindustry (vorallem Defense Maps)

  • Brillante Voraussage !

    • Mars
    • 1. September 2020 um 21:28

    Unter der Annahme, dass das "perfekte Demokratie" ist, ist diese Aussage tatsächlich nicht allzufalsch. Was mich stört ist folgendes: Es gibt sagen wir mal 10 Millionen Zitate von irgendwelchen wichtigen Leuten aus der (teils fernen) Vergangenheit. Es wurde vermutlich jede beliebige potentiell mögliche Zukünftige "Version" einer Präsidentschaft vorausgesagt (ich nenne das mal "Version" weil mir kein guter Begriff dafür eingefallen ist. Es geht hier um die "Art" der Regentschaft, also ein Schauspieler, ein Bauer oder ein Holzkopf, oder oder oder). Es ist vollkommen egal wer wann wo wie und warum gewählt wird, irgendwer innerhalb der letzten 200 Jahre hat es vorhergesagt, und dank Internet ist es heutzutage möglich effizient nach solchen Zitaten zu suchen, sodass man für jedes beliebige Ereignis eine passende Vorhersage findet, sofern man die Zeit investiert ein bisschen nachzuforschen.

    Ich hoffe das war verständlich^^

    M

  • Diskussion zu [Skripte] control hover effekt ohne fehler

    • Mars
    • 31. August 2020 um 10:06
    Zitat von Professor Bernd

    Ist alles schon drin, siehe Posting #1.

    Jaa ich habe ein bisschen den Überblick verloren :D

  • Diskussion zu [Skripte] control hover effekt ohne fehler

    • Mars
    • 30. August 2020 um 20:43

    Also wenn man es schonmal macht kann man auch direkt eine UDF daraus basteln^^

    Hier mal meine Interpretation der Angelegenheit (nicht ausgefeilt und nicht aufgeräumt, nur als Denkanstoß gedacht).

    AutoIt
    #include <Array.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <StructureConstants.au3>
    #include <WinAPIConstants.au3>
    #include <WinAPIConv.au3>
    #include <WinAPIInternals.au3>
    #include <WinAPISys.au3>
    #include <WinAPISysWin.au3>
    #include <WindowsConstants.au3>
    
    Opt("MustDeclareVars", 1)
    
    ; Das hier müsste man global halten (falls man eine UDF will ggf. ein neues Präfix erfinden z.B. __HP_ für HoverProc)
    Global $__aHoverProc[100] ; Hatte keine Lust auf eine Map, muss man aber eigentlich nutzen weil die IDs ja nicht unbedingt zusammenhängend sind.
    Global $__aHoverCtrl[0]
    Global $__hMouseProc = DllCallbackRegister("_MouseProc", "long", "int;wparam;lparam")
    Global $__hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($__hMouseProc), _WinAPI_GetModuleHandle(0))
    OnAutoItExitRegister('OnAutoItExit')
    
    ; Hier beginnt das eigentliche Skript vom User der UDF
    Global Const $COLOR_HOOVER = 0xD7EDFF ; helles grau
    Global Const $COLOR_NORMAL = 0xE6E6E6 ; helles blau
    Global $Form1 = GUICreate("Form1", 514, 330)
    Global $Label1 = GUICtrlCreateLabel("Label1", 96, 88, 92, 33, BitOR($SS_CENTER, $SS_CENTERIMAGE, $WS_BORDER))
    GUICtrlSetBkColor(-1, $COLOR_NORMAL)
    GuiCtrlSetHoverProc($Label1, HoverProc1)
    Global $Label2 = GUICtrlCreateLabel("Label2", 208, 88, 92, 33, BitOR($SS_CENTER, $SS_CENTERIMAGE, $WS_BORDER))
    GUICtrlSetBkColor(-1, $COLOR_NORMAL)
    ;~ GuiCtrlSetHoverProc($Label2, HoverProc1)
    Global $Label3 = GUICtrlCreateLabel("Label3", 320, 88, 92, 33, BitOR($SS_CENTER, $SS_CENTERIMAGE, $WS_BORDER))
    GUICtrlSetBkColor(-1, $COLOR_NORMAL)
    GuiCtrlSetHoverProc($Label3, HoverProc2)
    GUISetState(@SW_SHOW)
    
    While 1
        Local $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd
    
    ; Beispiel Proc 1
    Func HoverProc1($iCtrl, $bFocus)
        ; bFocus = True -> Maus ist in den Ctrl-Bereich eingetreten
        ; bFocus = False -> Maus ist aus dem Ctrl-Bereich herausgetreten
        If $bFocus Then
            GUICtrlSetBkColor($iCtrl, $COLOR_HOOVER)
        Else
            GUICtrlSetBkColor($iCtrl, $COLOR_NORMAL)
        EndIf
    EndFunc
    
    ; Beispiel Proc 2
    Func HoverProc2($iCtrl, $bFocus)
        If $bFocus Then
            GUICtrlSetData($iCtrl, 'Hover')
        Else
            GUICtrlSetData($iCtrl, 'Normal')
        EndIf
    EndFunc
    
    
    
    ; Das hier wären Funktionen für eine UDF #####
    Func OnAutoItExit()
        _WinAPI_UnhookWindowsHookEx($__hHook)
        DllCallbackFree($__hMouseProc)
    EndFunc   ;==>OnAutoItExit
    
    Func GuiCtrlSetHoverProc($iCtrl, $xFunc)
        $__aHoverProc[$iCtrl] = $xFunc
        _ArrayAdd($__aHoverCtrl, GUICtrlGetHandle($iCtrl))
    EndFunc
    
    Func _MouseProc($_nCode, $_wParam, $_lParam)
        Local Static $hLast
        If $_nCode > -1 Then
            Switch $_wParam
                Case $WM_MOUSEMOVE
                    Local $tPoint = DllStructCreate($tagPOINT, $_lParam)
                    Local $hRoot = _WinAPI_GetAncestor(_WinAPI_WindowFromPoint($tPoint), $GA_ROOT)
                    _WinAPI_ScreenToClient($hRoot, $tPoint)
                    Local $hChild = _WinAPI_ChildWindowFromPointEx($hRoot, $tPoint)
                    If IsHWnd($hChild) And $hChild <> $hLast Then
                        If $hLast <> $hRoot And _ArraySearch($__aHoverCtrl, $hLast) > -1 Then $__aHoverProc[_WinAPI_GetDlgCtrlID($hLast)](_WinAPI_GetDlgCtrlID($hLast), False)
                        If $hChild <> $hRoot And _ArraySearch($__aHoverCtrl, $hChild) > -1 Then $__aHoverProc[_WinAPI_GetDlgCtrlID($hChild)](_WinAPI_GetDlgCtrlID($hChild), True)
                        $hLast = $hChild
                    EndIf
            EndSwitch
        EndIf
        Return _WinAPI_CallNextHookEx($__hHook, $_nCode, $_wParam, $_lParam)
    EndFunc   ;==>_MouseProc
    ; ##########################################
    Alles anzeigen

    Also ansich fände ich es schlau, wenn man sich nicht auf die Hintergrundfarbe beschränkt, sondern in der mouseProc zu einer (frei wählbaren) AutoIt-Funktion weiterleitet die dann als "Hover Event" automatisch aufgerufen wird. Dann hat man vollen Zugriff auf das Ctrl und kann damit anstellen was auch immer man will. Wenn man das ganze wrappt hat man als einzige Funktion mit der der User Kontakt hat noch GuiCtrlSetHoverProc übrig, die Funktionen die man selbst schreiben muss (als User) sind so trivial, dass das jeder hinbekommen sollte (also das was im Hintergrund läuft sieht kompliziert aus, davon merkt der Anwender aber nichts).

    lg

    M

  • Brillante Voraussage !

    • Mars
    • 28. August 2020 um 14:37

    Trump bashing never gets old.

    Haben die unzähligen selbsternannten Propheten die voraussagten, dass die Welt (durch Trump) zugrundegerichtet wird und dass es einen Atomkrieg gibt, und und und... eigentlich nicht gemerkt, dass ihre Vorhersagen falsch waren? Jetzt geht ja die Runde, dass er mit militärischer Gewalt im Weißen Haus bleibt sollte er die Wahl verlieren. Und wenn das auch nicht stimmt denkt man sich eben wieder irgendeinen neuen Müll aus.

    Das soll jetzt nicht so rüberkommen, als würde ich den Holzkopf gutheißen, das soll nur zeigen, dass geschätze 95% der Kritik auch aus Idioten entspringt.

  • Gibt es eine "Tag"-Eigenschaft für Controls?

    • Mars
    • 18. August 2020 um 23:41

    Ich würde das ganze via Hashtable regeln.

    Ein Ctrl hat einige Eigenschaften die es mehr oder weniger eindeutig identifizieren:

    1. Ctrl-ID (Die Zahl die z.B. GuiCtrlCreateXYZ zurückgibt): kann mehrfach vergeben werden, wenn man Ctrls löscht.

    2. Handle (ein 32Bit Wert): habe kurz geschaut und es sieht so aus als würde selbst bei Neuerstellung eine um 0x10000 verschobene Adresse erzeugt werden.

    3. Ctrl-"Typ" (via GetWindowLong $GWL_WNDPROC, das ist eine vom Typ abhängige Adresse glaube ich): Ist für jeden CtrlTyp eindeutig.

    Bastel eine Hashfunktion mit Hash(ID, Handle, Typ) -> z.B. "Irgendein kurzer String" und benutze eine geeignete Liste (wie Dict, da gibt es aber noch weitere, schau dir die auch mal an) mit dem String als Key. Dann ist natürlich der Tag wieder nicht "direkt" an das Ctrl angehängt, aber man kann eine GuiCtrlGetTag/SetTag($iCtrl) Funktion schreiben, die über die ID an alles drankommt was gebraucht wird (ID, Handle, Typ) um einen eindeutigen Tag zuzuordnen.

    Allerdings müsstest du ggf. alte Tags löschen (also eine benutzerdefinierte GuiCtrlDelete-Funktion basteln), weil AutoIt-Intern soweit ich weiß keine direkte Möglichkeit besteht etwas "vor den destruktor" zu schieben, sodass das automatisch ausgeführt wird. Aber man weiß ja nie, villeicht kann man über ein paar dreckige Tricks an den Pointer kommen, diesen Umleiten (in eine eigene Proc) und von da aus wieder an den Interpreter weiterleiten. :D

    M

  • [GDI+] Casteljau Beispiel & Bezier Beispiel

    • Mars
    • 16. August 2020 um 15:04

    Schön, dass es euch gefällt. Ja im Prinzip ist Casteljau eine coole Sache, aber (in dieser Form) nicht der Way to go (Beschränktheit auf durch 4 teilbare Punktmengen (bzw wenn man garnichts ändert nur auf 4 Punkte^^), diskrete Punktmenge als Ergebnis (ich kann nicht einfach sagen, dass ich z.B. 50 Punkte für die neue Kurve will, ich bekomme je nach Iterationsschritt eben so viele wie ich bekomme), usw usw.

    Da ich sowieso noch ein weiteres Beispiel gebraucht habe hab ich noch ein bisschen mehr Spielzeug für UEZ :D

    PS: Die Methode geht in einer pointerbasierten Programmiersprache bestimmt richtig steil, in AutoIt hat man hier ziemlich viel overhead.

    AutoIt
    #include <GDIPlus.au3>
    #include <Misc.au3>
    
    Opt('GUIOnEventMode', 1)
    Opt('MouseCoordMode', 2)
    
    Global Const $sTitle = 'BezierN'
    Global Const $iW = 768
    Global Const $iH = 768
    Global Const $nBezierPoints = 35
    
    Global $aKontrollPunkte[0]
    AddPoint($aKontrollPunkte, 0.1, 0.2)
    AddPoint($aKontrollPunkte, 0.1, 0.3)
    AddPoint($aKontrollPunkte, 0.3, 0.7)
    AddPoint($aKontrollPunkte, 0.6, 0.8)
    AddPoint($aKontrollPunkte, 0.9, 0.2)
    AddPoint($aKontrollPunkte, 0.9, 0.9)
    AddPoint($aKontrollPunkte, 0.5, 0.5)
    
    Func AddPoint(ByRef $a, $x, $y)
        Local $z = [$x, $y], $u = UBound($a)
        ReDim $a[$u + 1] ; Jaaah macht man ja nur 1x am Anfang. Bitte NICHT oft nutzen, langsam.
        $a[$u] = $z
    EndFunc
    
    Global $aBezierN = BezierN($aKontrollPunkte, $nBezierPoints)
    
    ; Input : Array[i] = Array[2] = [x, y] für beliebige Punktmengen
    ; Output: Array[i] = Array[2] = [x, y] mit $n Einträgen
    Func BezierN(ByRef $aPoints, $n = 25)
        Local $u = UBound($aPoints), $aBuf[$u][2], $aRet[$n], $r = 0, $t = 0, $a[2], $b[2], $c[2], $m = 0
        For $tt = 0 To $n - 1 Step 1
            $t = $tt / ($n - 1)
            For $i = 0 To $u - 1 Step 1
                $aBuf[$i][0] = $aPoints[$i]
            Next
            For $sub = 2 To $u Step 1
                $m = IsInt($sub/2)
                For $i = 0 To $u - $sub Step 1
                    $a = $aBuf[$i][1-$m]
                    $b = $aBuf[$i+1][1-$m]
                    $c[0] = $a[0] + $t * ($b[0] - $a[0])
                    $c[1] = $a[1] + $t * ($b[1] - $a[1])
                    $aBuf[$i][$m] = $c
                    If $sub = $u Then
                        $aRet[$r] = $aBuf[$i][$m]
                        $r += 1
                    EndIf
                Next
            Next
        Next
        Return $aRet
    EndFunc
    
    Global $bExit = False
    
    _GDIPlus_Startup()
    Global $hGUI = GUICreate($sTitle, $iW, $iH)
    Global $hGFX = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Global $hBMP = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGFX)
    Global $hBUF = _GDIPlus_ImageGetGraphicsContext($hBMP)
    Global $hPEN = _GDIPlus_PenCreate()
    
    _GDIPlus_PenSetStartCap($hPEN, 2)
    _GDIPlus_PenSetEndCap($hPEN, 2)
    _GDIPlus_GraphicsSetSmoothingMode($hBUF, 2)
    
    GUISetOnEvent(-3, 'EVENT', $hGUI)
    OnAutoItExitRegister('Xit')
    GUISetState(@SW_SHOW, $hGUI)
    
    While Not $bExit And Sleep(10)
        _GDIPlus_GraphicsClear($hBUF)
        $aBezierN = BezierN($aKontrollPunkte, $nBezierPoints)
        Print($aBezierN, 0.015, 0xFFFF6050)
        Print($aKontrollPunkte, 0.025, 0xFF808080)
        Mouse($aKontrollPunkte)
        _GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP, 0, 0, $iW, $iH)
    WEnd
    
    Func Mouse(ByRef $aPoints)
        Local $mPos = MouseGetPos(), $a[2]
        Local Static $iDrag = -1
        _GDIPlus_PenSetColor($hPEN, 0xFF80FF00)
        _GDIPlus_PenSetWidth($hPEN, (0.035 / 5.0) * $iW)
        _GDIPlus_PenSetDashStyle($hPEN, 0)
        For $i = 0 To UBound($aPoints) - 1 Step 1
            If Sqrt(($mPos[0]/$iW - ($aPoints[$i])[0])^2 + ($mPos[1]/$iH - ($aPoints[$i])[1])^2) < 0.0325 Then
                If _IsPressed('01') Then
                    $iDrag = $i
                Else
                    $iDrag = -1
                EndIf
                Circle($aPoints[$i], 0.035)
            EndIf
        Next
        If $iDrag <> -1 Then
            $a[0] = $mPos[0] / $iW
            $a[1] = $mPos[1] / $iH
            $aPoints[$iDrag] = $a
        EndIf
    EndFunc
    
    Func Print(ByRef $aPoints, $d = 0.025, $iCol = 0xFFFFFFFF)
        _GDIPlus_PenSetColor($hPEN, $iCol)
        _GDIPlus_PenSetWidth($hPEN, ($d / 5.0) * $iW)
        _GDIPlus_PenSetDashStyle($hPEN, 0)
        For $i = 0 To UBound($aPoints) - 1 Step 1
            Circle($aPoints[$i], $d)
        Next
        _GDIPlus_PenSetWidth($hPEN, ($d / 8.0) * $iW)
        _GDIPlus_PenSetDashStyle($hPEN, 1)
        For $i = 0 To UBound($aPoints) - 2 Step 1
            Line($aPoints[$i], $aPoints[$i+1])
        Next
    EndFunc
    
    Func Line($p1, $p2)
        _GDIPlus_GraphicsDrawLine($hBUF, $p1[0] * $iW, $p1[1] * $iH, $p2[0] * $iW, $p2[1] * $iH, $hPEN)
    EndFunc
    
    Func Circle($p, $d)
        _GDIPlus_GraphicsDrawEllipse($hBUF, $p[0] * $iW - $d/2 * $iW, $p[1] * $iH - $d/2 * $iH, $d * $iW, $d * $iH, $hPEN)
    EndFunc
    
    Func EVENT()
        Switch @GUI_CtrlId
            Case -3
                $bExit = True
        EndSwitch
    EndFunc
    
    Func Xit()
        _GDIPlus_PenDispose($hPEN)
        _GDIPlus_GraphicsDispose($hBUF)
        _GDIPlus_BitmapDispose($hBMP)
        _GDIPlus_GraphicsDispose($hGFX)
        _GDIPlus_Shutdown()
    EndFunc
    Alles anzeigen

    Der Algorithmus ist für beliebige Punktmengen nutzbar, hat aber n² Komplexität (in Bezug auf die Menge der Eingabepunkte) und lineare Komplexität in Bezug zum Output (also wenn man z.B. 100 Punkte statt 50 haben will). Er hat noch tonnenweise weitere Nachteile (z.B. ist "alles" verknüpft, selbst bei 10 Eingabepunkten bewirkt eine Bewegung eines Randpunktes veränderungen an der ganzen Kurve, auch wenn die Veränderungen klein sind), aber das ist schon so geplant ;)

    Wenn jemand Lust hat kann er ja ein Beispiel für B-Splines (via BezierN frei wählbarer Grad) basteln, dann hat man bessere lokale Eigenschaften und bessere Komplexität :)

    Edit: Und noch eine Version mit Pseudo Äquidistanten Punkten (auch O(n²)):

    AutoIt
    #include <GDIPlus.au3>
    #include <Misc.au3>
    #include <Array.au3>
    
    Opt('GUIOnEventMode', 1)
    Opt('MouseCoordMode', 2)
    
    Global Const $sTitle = 'BezierN_PseudoEquidistant'
    Global Const $iW = 512
    Global Const $iH = 512
    Global Const $nBezierPoints = 50
    
    Global $aKontrollPunkte[0]
    AddPoint($aKontrollPunkte, 0.1, 0.2)
    AddPoint($aKontrollPunkte, 0.1, 0.3)
    AddPoint($aKontrollPunkte, 0.3, 0.7)
    AddPoint($aKontrollPunkte, 0.6, 0.8)
    AddPoint($aKontrollPunkte, 0.9, 0.2)
    AddPoint($aKontrollPunkte, 0.9, 0.9)
    AddPoint($aKontrollPunkte, 0.5, 0.5)
    
    Func AddPoint(ByRef $a, $x, $y)
        Local $z = [$x, $y], $u = UBound($a)
        ReDim $a[$u + 1] ; Jaaah macht man ja nur 1x am Anfang. Bitte NICHT oft nutzen, langsam.
        $a[$u] = $z
    EndFunc
    
    Global $aBezierN = BezierN($aKontrollPunkte, $nBezierPoints)
    
    ; Input : Array[i] = Array[2] = [x, y] für beliebige Punktmengen
    ; Output: Array[i] = Array[2] = [x, y] mit $n Einträgen
    Func BezierN(ByRef $aPoints, $n = 25)
        Local $u = UBound($aPoints), $aBuf[$u][2], $aRet[$n], $r = 0, $t = 0, $a[2], $b[2], $c[2], $m = 0
        For $tt = 0 To $n - 1 Step 1
            $t = $tt / ($n - 1)
            For $i = 0 To $u - 1 Step 1
                $aBuf[$i][0] = $aPoints[$i]
            Next
            For $sub = 2 To $u Step 1
                $m = IsInt($sub/2)
                For $i = 0 To $u - $sub Step 1
                    $a = $aBuf[$i][1-$m]
                    $b = $aBuf[$i+1][1-$m]
                    $c[0] = $a[0] + $t * ($b[0] - $a[0])
                    $c[1] = $a[1] + $t * ($b[1] - $a[1])
                    $aBuf[$i][$m] = $c
                    If $sub = $u Then
                        $aRet[$r] = $aBuf[$i][$m]
                        $r += 1
                    EndIf
                Next
            Next
        Next
        Return $aRet
    EndFunc
    
    Func BezierN_PseudoEquidistant(ByRef $aPoints, $n = 25)
        Local $BN = BezierN($aPoints, $n), $l = 0, $at[$n][2], $eps = 1e-6
        For $i = 0 To $n - 2 Step 1
            $l += Sqrt((($BN[$i])[0] - ($BN[$i+1])[0])^2 + (($BN[$i])[1] - ($BN[$i+1])[1])^2)
            $at[$i+1][0] = ($i + 1) /($n - 1)
            $at[$i+1][1] = $l
        Next
        Local $ls = $l / ($n - 1), $newT[$n] = [0], $ii = 0, $minI = 0
        For $i = 0 To $n - 2 Step 1
            For $o = $ii To $n - 2 Step 1 ; hier bin ich nicht sicher ob ein invalides $ii auftreten kann...
                If $ls * ($i + 1) >= ($at[$o][1] - $eps) And $ls * ($i + 1) <= ($at[$o+1][1] + $eps) Then
                    $ii = $o
                    ExitLoop
                EndIf
            Next
            $newT[$i + 1] = $at[$ii][0] + ($ls * ($i + 1) - $at[$ii][1]) / ($at[$ii+1][1] - $at[$ii][1]) * ($at[$ii+1][0] - $at[$ii][0])
        Next
        Local $u = UBound($aPoints), $aBuf[$u][2], $aRet[$n], $r = 0, $t = 0, $a[2], $b[2], $c[2], $m = 0
        For $tt = 0 To $n - 1 Step 1
            $t = $newT[$tt]
            For $i = 0 To $u - 1 Step 1
                $aBuf[$i][0] = $aPoints[$i]
            Next
            For $sub = 2 To $u Step 1
                $m = IsInt($sub/2)
                For $i = 0 To $u - $sub Step 1
                    $a = $aBuf[$i][1-$m]
                    $b = $aBuf[$i+1][1-$m]
                    $c[0] = $a[0] + $t * ($b[0] - $a[0])
                    $c[1] = $a[1] + $t * ($b[1] - $a[1])
                    $aBuf[$i][$m] = $c
                    If $sub = $u Then
                        $aRet[$r] = $aBuf[$i][$m]
                        $r += 1
                    EndIf
                Next
            Next
        Next
        Return $aRet
    EndFunc
    
    Global $bExit = False
    
    _GDIPlus_Startup()
    Global $hGUI = GUICreate($sTitle, $iW, $iH)
    Global $hGFX = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Global $hBMP = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGFX)
    Global $hBUF = _GDIPlus_ImageGetGraphicsContext($hBMP)
    Global $hPEN = _GDIPlus_PenCreate()
    
    _GDIPlus_PenSetStartCap($hPEN, 2)
    _GDIPlus_PenSetEndCap($hPEN, 2)
    _GDIPlus_GraphicsSetSmoothingMode($hBUF, 2)
    
    GUISetOnEvent(-3, 'EVENT', $hGUI)
    OnAutoItExitRegister('Xit')
    GUISetState(@SW_SHOW, $hGUI)
    
    While Not $bExit And Sleep(10)
        _GDIPlus_GraphicsClear($hBUF)
        $aBezierN = BezierN_PseudoEquidistant($aKontrollPunkte, $nBezierPoints)
        Print($aBezierN, 0.015, 0xFFFF6050)
        Print($aKontrollPunkte, 0.025, 0xFF808080)
        Mouse($aKontrollPunkte)
        _GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP, 0, 0, $iW, $iH)
    WEnd
    
    Func Mouse(ByRef $aPoints)
        Local $mPos = MouseGetPos(), $a[2]
        Local Static $iDrag = -1
        _GDIPlus_PenSetColor($hPEN, 0xFF80FF00)
        _GDIPlus_PenSetWidth($hPEN, (0.035 / 5.0) * $iW)
        _GDIPlus_PenSetDashStyle($hPEN, 0)
        For $i = 0 To UBound($aPoints) - 1 Step 1
            If Sqrt(($mPos[0]/$iW - ($aPoints[$i])[0])^2 + ($mPos[1]/$iH - ($aPoints[$i])[1])^2) < 0.0325 Then
                If _IsPressed('01') Then
                    $iDrag = $i
                Else
                    $iDrag = -1
                EndIf
                Circle($aPoints[$i], 0.035)
            EndIf
        Next
        If $iDrag <> -1 Then
            $a[0] = $mPos[0] / $iW
            $a[1] = $mPos[1] / $iH
            _GDIPlus_PenSetColor($hPEN, 0xFF80FFFF)
            Circle($aPoints[$iDrag], 0.035)
            $aPoints[$iDrag] = $a
        EndIf
    EndFunc
    
    Func Print(ByRef $aPoints, $d = 0.025, $iCol = 0xFFFFFFFF)
        _GDIPlus_PenSetColor($hPEN, $iCol)
        _GDIPlus_PenSetWidth($hPEN, ($d / 5.0) * $iW)
        _GDIPlus_PenSetDashStyle($hPEN, 0)
        For $i = 0 To UBound($aPoints) - 1 Step 1
            Circle($aPoints[$i], $d)
        Next
        _GDIPlus_PenSetWidth($hPEN, ($d / 8.0) * $iW)
        _GDIPlus_PenSetDashStyle($hPEN, 1)
        For $i = 0 To UBound($aPoints) - 2 Step 1
            Line($aPoints[$i], $aPoints[$i+1])
        Next
    EndFunc
    
    Func Line($p1, $p2)
        _GDIPlus_GraphicsDrawLine($hBUF, $p1[0] * $iW, $p1[1] * $iH, $p2[0] * $iW, $p2[1] * $iH, $hPEN)
    EndFunc
    
    Func Circle($p, $d)
        _GDIPlus_GraphicsDrawEllipse($hBUF, $p[0] * $iW - $d/2 * $iW, $p[1] * $iH - $d/2 * $iH, $d * $iW, $d * $iH, $hPEN)
    EndFunc
    
    Func EVENT()
        Switch @GUI_CtrlId
            Case -3
                $bExit = True
        EndSwitch
    EndFunc
    
    Func Xit()
        _GDIPlus_PenDispose($hPEN)
        _GDIPlus_GraphicsDispose($hBUF)
        _GDIPlus_BitmapDispose($hBMP)
        _GDIPlus_GraphicsDispose($hGFX)
        _GDIPlus_Shutdown()
    EndFunc
    Alles anzeigen

    Die Methodik hier ist:

    1. Berechne die "normalen" Bezier Punkte
    2. Man kennt jetzt zu jedem Punkt den Abstand zum Nachfolger UND das $t welches in der originalen Version äquidistant verteilt wurde
    3. Jetzt berechnet man pi mal Daumen die Gesamtlänge der Kurve (ist natürlich nicht exakt weil man endliche Samples hat)

    4. Man kennt jetzt den Mittleren Abstand und findet ein modifiziertes $t, sodass der Abstand bei jedem Punkt zu seinem Vorgänger gleich ist.

    Da das ganze unter der Annahme ist, dass man die Gesamtlänge der Kurve kennt (die man nicht kennt), sowie das die Kurve lokal eine kleine Änderungsrate hat (was oft nicht stimmt, wir sagen hier immerhin, dass das Integral entlang der Kurve GLEICH dem Abstand 2er Punkte ist. Nur ein Narr glaubt dass das immer geht) funktioniert die Methode nur wenn man hinreichend viele Punkte hat. Im Beispiel kann man z.B. mal eine 5 eintragen und sehen dass die Punkte KEINE gleichmäßige Abstände haben. Verwendbar wenn man genügend Punkte, und eine Kurve ohne zu stark knickende Stellen hat. Verwendungszweck: Wenn man aus irgendwelchen Gründen (z.B. Simulationen) halbwegs gleiche Abstände braucht, in 99% aller anderen Fälle ist der normale Bezier besser.

    lg

    M

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™