Drehung und Projektion einer Ebene.
- VB.NET
- .NET (FX) 4.5–4.8
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.
-
-
-
-
@Bartosz
Bartosz schrieb:
@-Franky- Danke für den Link. Wie kann ich das einbauen / aufrufen? Hast du ein kleines Beispiel?
Im Prinzip läuft die ganze Geschichte dann über diverse WIC-, D2D1-, D3D11- und DXGI-COM Interfaces (WIC nur weil ich darüber das Bild von der Platte lade). Das kann man nicht so einfach erklären bzw. würde hier den Rahmen sprengen. Das was Du auf dem Bild von mir siehst, ist mal vor 2 Jahren in VB6 entstanden. Entsprechend habe ich auch nur VB6-Code. Das nach .NET umzubauen, ohne Fremdkomponenten\Wrapper\Verweise, wäre zwar machbar, braucht aber halt viel Zeit und man muss sich mit DirectX beschäftigen. Allein das Interface ID2D1DeviceContext besitzt schon sehr viele Funktionen und erbt Funktionen von ID2D1RenderTarget und das wiederum Funktionen von ID2D1Resource und das von IUnknown. Gebraucht werden aber nur ein paar Funktionen aus diesen COM Interfaces. Nur allein diese COM Interfaces direkt in .NET einzubauen ist schon eine Aufgabe (das ist in VB6 bedeutend einfacher), falls man keine externen Komponenten, Wrapper bzw Verweise verwenden möchte.
Falls Du Dich dennoch darin einlesen möchtest:
docs.microsoft.com/en-us/windo…ply-effects-to-primitives
docs.microsoft.com/en-us/windo…vices-and-device-contextsMfg -Franky- -
Vielleicht ist das ja hilfreich:
Es gibt verschiedene Arten etwas zu Projizieren, hier in aller Kürze ein paar:
Projektion auf die XY-Ebene:
$P_{xy} = \begin{pmatrix}1 & 0 & 0 \\ 0 &1 & 0 \\ 0 & 0 & 0 \end{pmatrix}$
Multipliziert man einen Vektor$(x,y,z)^T$mit der Matrix$P_{xy}$werden nur die X,Y Komponenten verwendet:
$ P_{xy} \cdot \begin{pmatrix}x \\ y \\ z \end{pmatrix} = \begin{pmatrix}1 & 0 & 0 \\ 0 &1 & 0 \\ 0 & 0 & 0\end{pmatrix} \begin{pmatrix}x \\ y \\ z \end{pmatrix} = \begin{pmatrix}x \\ y \\ 0 \end{pmatrix}$
Projektion auf die Z-Achse:
$P_{z} = \begin{pmatrix}0 & 0 & 0 \\ 0 &0 & 0 \\ 0 & 0 & 1\end{pmatrix}$
Multipliziert man einen Vektor$(x,y,z)^T$mit der Matrix$P_{z}$wird nur die Z Komponente verwendet:
$P_{z} \cdot \begin{pmatrix}x \\ y \\ z \end{pmatrix}= \begin{pmatrix}0 & 0 & 0 \\ 0 &0 & 0 \\ 0 & 0 & 1\end{pmatrix} \cdot \begin{pmatrix}x \\ y \\ z \end{pmatrix} = \begin{pmatrix}0 \\ 0 \\ z \end{pmatrix}$
Translation:
$\begin{pmatrix} 1 & 0 & 0 & X \\ 0 & 1 & 0 & Y \\ 0 & 0 & 1 & Z \\ 0 & 0 & 0 & 1\end{pmatrix}\begin{pmatrix} a_1 \\ a_2 \\ a_3 \\ 1\end{pmatrix} = \begin{pmatrix} a_1 + X \\ a_2 + Y \\ a_3 + Z \\ 1\end{pmatrix} $
Allgemein wird eine Projektionsmatrix zu einem Vektor$\mathbf{a}$so bestimmt:
$P = \frac{aa^T}{a^Ta}$
Das ist recht nett, weil mit$P$kann ich nun jeden Vektor$\mathbf{b}$auf$\mathbf{a}$projizieren
Vielleicht noch nebenbei gesagt, der Punkt in deiner Gleichung oben mit dem$N$ist, dass es sich hierbei um ein Skalarprodukt handelt!
Dieser Beitrag wurde bereits 17 mal editiert, zuletzt von „VB.neter0101“ ()
-
@Bartosz
Ich gesell mich auch noch kurz dazu.
Dein Projekt in #5 habe ich mir kurz runtergeladen. Scheint mir tatsächlich ein schöner Gimbal Lock Effekt zu sein.
de.wikipedia.org/wiki/Gimbal_Lock
Und wahrscheinlich hast du es mittlerweile schon gelöst bekommen.
Ich habe dir hier zwei Links für die gewünschten Matrix-Formeln.
Einfach eine genial erklärte Übersicht. Besser findet man es wahrscheinlich nirgendswo.
docplayer.org/30910350-Repraes…ometrischen-objekten.html
Und hier eine weitere kleine gute Zusammenfassung.
cg.tuwien.ac.at/courses/CG1/textblaetter/02 Geometrische Transformationen.pdf
Eventuell wäre ein Wechsel zu den Quaternionen auch eine passende Alternative. Anschauen lohnt sich auf jeden Fall.
https://de.wikipedia.org/wiki/Quaternion
cbcity.de/tutorial-rotationsma…n-din70000-zyx-konvention
Freundliche Grüsse
exc-jdbi -
Hallo @VB.neter0101 und @exc-jdbi
Danke für eure Antworten. Ich habe bis jetzt an einer neuen Lösung gesessen, habe ne neue Klasse geschrieben, da Vb.neter0101 mich auf eine Idee gebracht hat. @exc-jdbi Deine Links schaue ich mir morgen an. -
Gut, ich hab's nun ein wenig anders gemacht. Ich wollte eh von trigonometrischen Funktionen weg...
Folgendes Beispiel: Ich habe wieder meine um 20° um die y-Achse gedreht Ebene. Wieder mit dem Online-Tool gezeichnet. Ich habe festgestellt, dass das Tool die Ansicht bös falsch darstellt. Die Ebene wird viel länger gezeichnet, als sie zu sein hat. Logisch, denn ich kann ja keine Begrenzung eingeben, demnach läuft sie nach mathematischer Definition ins Unendliche und das Tool stellt sie viel breiter dar, als sie sein soll. Also nehmen wir an, die Ebene soll 10 LE in jede Richtung haben. Also endet sie an den roten Linien, die ich ins Bild gezeichnet habe!
Ich habe, wie im letzten Post erwähnt, eine neue Klasse geschrieben. Hier ist die Dokumentation.
Vektor a1 läuft auf der Ebene mit, a2 ist der runterprojizierte Vektor (danke hier an @VB.neter0101). a2 ist also die blanke Entfernung vom Ursprung zum Rand, und das Ganze$ ursprüngliche Länge der Ebene \cdot cos(α)$, da die Seite beim Drehen kleiner aussehen muss. In die andere Richtung läuft b2, der hat einfach nur ein anderes Vorzeichen, also auch nichts Schlimmes.
Um jetzt von a2 nach oben in die linke Ecke zu kommen – und da hab ich mich in der Vergangenheit etwas schwer getan – habe ich jetzt mal probehalber C1 gebildet. Der Vektor läuft auf der Ebene lang. Ich habe festgestellt, C2 ist einfach der Pythagoras von der eingestellten Größe (10) und der z-Komponente der Ebene, also$\sqrt(10^{2}+3,4202^{2})=10,568 $.
Die rechte Seite, C3, ist dann$ 10-( \sqrt(10^{2}+3,4202^{2})-10)=9,43 $
Ja, und nach unten einfach umgekehrte Vorzeichen.
Für die Drehung um die x-Achse gilt: was links unten war, wird links oben. xneu = y und yneu = -x
Worum ich euch gerne bitten würde: Sieht das für euch korrekt aus?
Ich lade mal das Projekt hoch. Mit dieser Form könnt ihr eine neue Ebene erstellen. Die Zahlen bitte erstmal so lassen, weil ich noch nicht alle erdenklichen Kombinationen implementiert habe. Die Ebene drehen könnt ihr mit W, A , S, D (aber ein Winkel von beiden muss immer 0° sein).
Drehung einer Ebene.zip
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Bartosz“ ()
-
Bartosz schrieb:
Sieht das für euch korrekt aus?
ich hab nicht jedes Detail gelesen, folge diesem Thread aber mit Interesse.
Grad fällt mir ein, dass zur Darstellung der perspektivischen Verkürzung ein entscheidender Faktor noch garnet erwähnt wurde (oder ich übersehen): Die Position der Kamera.
Weil je näher ein Beobachter an einem Objekt dran ist, desto stärker wirkt sie sich aus.
Oder anders: Womöglich jedes Viereck sieht richtig aus als Projektion einer gedrehten Ebene. Ist nur eine Frage der CameraPosition.
-
Hallo @ErfinderDesRades "Weil je näher ein Beobachter an einem Objekt dran ist, desto stärker wirkt sie sich aus." Korrekt. Die Kameraposition ist noch nicht im Code implementiert, weil ich erst einmal das perspektivische Zeichnen schaffen möchte.
-
-
Ich habe noch ne gute Idee, wie man das Ganze besser berechnet (mit den Mitteln die ich habe). Ich muss nur im Programm aus der Parameterform der Ebene die Koordinatenform machen können und dann eine Gerade in die Ebenengleichung (daher KO-Form) einsetzen, um den Durchstoßpunkt zu berechnen. Ich habe mir NCalc heruntergeladen. Das Problem: Es ist irre langsam. Kennt hier jemand bitte eine Möglichkeit, dies zu verwursten und s zu finden? Im Programm? Das müsste schon auf die 3te Nachkommastelle genau sein... Ich habe versucht, das mit ne For-Schleife zu machen, aber das Programm hat mir die Nachkommastellen versaut. Es kam (nach Minuten) s = 0,9.. heraus
total langsam
VB.NET-Quellcode
- For i As Double = 0 To 1 Step 0.0001
- Zwischenspeicher = alles_verrechnet.Replace("s", i.ToString())
- Zwischenspeicher = Zwischenspeicher.Replace(","c, "."c)
- Dim This As New NCalc.Expression(Zwischenspeicher)
- Ergebnis = CDbl(This.Evaluate)
- Debug.WriteLine(CInt(Ergebnis * 1000.0))
- If CInt(Ergebnis * 1000.0) = 0 OrElse CInt(Ergebnis * 1000.0) = 1 OrElse CInt(Ergebnis * 1000.0) = -1 Then
- yFuerDSP = i
- End If
- Next
Schönen FußballabendDieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()
-
-
Hallo @VB.neter0101, auf meinem Bild , erste Zeile, das ist bereits die Koordinatenform, die ich mit dem Kreuzprodukt berechnet habe. Meine Frage war, ob das das Programm machen könnte. Das habe ich auch hinbekommen. Dann aber muss die Gerade* eingesetzt werden und wie du siehst ergibt das einen langen Term mit Buchstaben drin . Meine Frage war gestern Abend, ob mein Programm verrechnen könnte, was geht, um letzten Endes auf z.B.
-31,507*s+28,294=0
zu kommen. Dann muss ich nämlich nicht solven, um an s zu kommen, sondern kann einfach 28,294 durch 31,507 dividieren. Naja, das habe ich verworfen. Ich habe es anders gemacht. Dazu gleich mehr.
*Von welcher Gerade redet er?
Ich habe mir das nun so gedacht. Ich habe einmal die gedrehte Ebene (lila) und einmal die runterprojizierte (grün). Bitte beachte, dass sie im Onlinetool korrekt in x-Richtung etwas kleiner geworden ist, aber in y-Richtung zu groß dargestellt wird. Das ist einfach eine Sache des Tools. Und jetzt nutze ich die Kameraposition, wie von @ErfinderDesRades erwähnt. Sie ist zwar fix, aber von ihr geht ein Vektor zy1 auf die Ecke der gekippten Ebene. Es gibt auch einen Vektor von der Kamera auf die platte Ebene, er heißt zyplatt. Wie man sieht, durchstößt zyplatt auf seinem Weg die gekippte Ebene. Schau mal auf die Stelle. Von dort aus muss ich nur weiter hoch (y erhöhen). Aber wie viel? Das geht, wenn man den Durchstoßpunkt berechnet und die Differenz y des zyplatt und y des DSP nimmt und dieses Differenz-y für den Vektor Kante nutzt. 10+(10-8,98) = 11,02. Ja, dazu brauchte ich gestern Abend die Automatisierung: Koordinatenform bilden, Gerade einsetzen, Durchstoßpunkt berechnen.
Ich hatte es gestern Nacht noch so gelöst, dass ich mir einfach alle Werte bei Excel generiert habe. So konnte ich einen Faktor bilden und weiß nun, um wie viel breiter die Ebene in y-Richtung bei Drehung aussehen muss.
Das werde ich heute programmieren. Mal schauen, wie's wird. -
Kurzes Update: diesen Thread werde ich bis auf Weiteres pausieren.
1.)
Ich hatte Folgendes gemacht. Ich habe ein "Spinnennetz" von der Kamera aus zu den 4 Eckpunkten gebildet. Das sind meine Vektoren. Aber: Wir reden von der runterprojizierten Ebene (grün), die auch zusammenschrumpft. Der eine Vektor durchstößt auf seinem Weg die lilane Ebene, und von diesem Durchstoßpunkt, den ich berechnen kann, gehe ich etwas in y-Richtung hoch und schon bin ich auf der Kante und weiß, um wie viel breiter die lilane Ebene erscheint, also wie ich die grüne zeichnen muss... Tja, hat besser geklappt als am Anfang dieses Threads, weil ich auch von cos und sin weg bin... Jedoch kam es bei 2 großen Winkeln immer noch zu einer Verzerrung.
Ich habe jetzt 3 Tage Pause gemacht und habe heute Nachmittag mit meinem Nachbarn gesprochen. (Das ist auch so ne Sache..wen soll ich fragen...dafür kann keiner was, aber ist halt so.) Er sagte, dieses Online-Tool arbeitet mit einer 3D-Darstellung und Code, der das verarbeiten kann. Das Tool weiß aus jedem Blickwinkel (x,y,z), wie die Szenerie auszusehen hat. Es ist eine 3D-Engine. Sie könnte auch die Natur wiedergeben. Es wurde ja eigentlich nur ein lilanes Rechteck gemalt und das Tool weiß - aus jedem Blickwinkel, wie das auszusehen hat. Eine mathematische Ebene wird ja auch in der Schule durch 3 Achsen definiert... Selbst, wenn ich die Ebene im Tool plattdrücke (z=0), und mich gefreut habe, dass es richtig aussieht (weil die platte kürzer wird), so ist das trotzdem falsch, denn ich gehe vom falschen System aus. So, wie ich das programmiert habe, sah die Projektion ja nur gut aus, wenn ich um eine Achse gedreht habe. Kam eine zweite Drehung um eine andere Achse dazu, hatte ich diese Verzerrung. Das ist genau der Punkt. Er hat ein Poster gesehen, bei dem Bahnschienen genau in die Bildtiefe gehen. Und er hat gesagt, "schau mal, du siehst hier an den Bahnschienen sehr schön die räumliche Tiefe (trotz dieses 2D-Posters), die Original-Szenerie kommt aber aus einer echten 3D-Welt. Würdest du jetzt das so kopierend programmieren, also fester Blickwinkel, und das Bild um beide Achsen kippen, wären die Schienen nicht mehr gerade, sondern so mit steigender Tiefe immer verzerrter / "verbogener" wie bei dir im Programm." Es ist also ein Unterschied im Kopf zu machen (auch wenn man denkt "Es wird ja immer sowieso alles auf einem 2D-Monitor projiziert"), ob man entweder eine 3D-(Spiele)-Welt baut, oder ob sie nicht vorhanden ist und man einen 3D-Sachverhalt aus der echten Welt nachahmen will. Der letztere Fall trifft bei mir zu. Eine Lösung kann sein, ein 2D-Array zu kreieren, welches für den Menschen so aussieht, als wäre es eine 3D-Welt... Das Array ist aber nie 3D gewesen. Wenn man Spiele entwickelt, sagt er, wird das auch so gemacht. Das macht dir die 3D-Engine.
Na gut, durch Fehler lernt man... Hätte ich immer gleich aufgegeben, wär ich heut nicht da, wo ich bin.
Wir können gerne noch etwas drüber diskutieren. Ich musste mir auch gerade Mühe geben, das in Worte zu fassen. Gar nicht so einfach online...
Ich bedanke mich bei allen, die hier einen Beitrag geschrieben haben. , bleibt gesund, ich mach bestimmt bald wieder den nächsten Thread auf.
Viele Grüße
Bartosz
Achja, und falls doch noch einer was weiß, immer her damit.
-
Lösung
Allgemein löst man eine Projektion so, als würde man im realen Leben durch ein Fenster nach draußen sehen und dort etwas beobachten. Im Auge laufen alle Linien zusammen. Dies habe ich einmal mit dem Online-Tool dargestellt. Am Koordinatenursprung sei das Auge; und die Linien, die von markanten Punkten – den Ecken – des Quaders kommen, werden auf dem Fenster (grüne Ebene) dargestellt.
Wer das eingeben möchte:
Link und Formeln für das Online-Tool
matheretter.de/geoservant/de
quader(8|0|1 2|2|3)[00 -35 0]
ebene(2|0|0 2|0|2 2|2|0)
vektor(0|0|0 7,31|0|3,15 "a")
vektor(0|0|0 7,31|2|3,15 "b")
vektor(0|0|0 9|0|0,7 "c")
vektor(0|0|0 9|2|0,7 "d")
vektor(0|0|0 9|2|4,25 "e")
vektor(0|0|0 9|0|4,25 "f")
vektor(2|0|0 0|0|0,8618 "p1")
vektor(2|0|0 0|0,547|0,8618 "p2")
vektor(2|0|0 0|0|0,1555 "p3")
vektor(2|0|0 0|0,4444|0,9444 "p4")
Die 2D-Vektoren werden wie folgt berechnet (Achtung, in diesem Beispiel läuft +x Richtung Quader, +y nach links und z nach oben):
$$ z_{neu} = \frac{d}{x} \cdot z $$mit d = Abstand Auge zum Fenster; z = z-Komponente des Vektors vom Ursprung zum Quader
$$ y_{neu} = \frac{d}{x} \cdot y $$mit d = Abstand Auge zum Fenster; y = y-Komponente des Vektors vom Ursprung zum Quader.
Konkretes Beispiel: Wir nehmen den Vektor a = (0|0|0 7,31|0|3,15)
$$ \frac{2}{7.31} \cdot 3.15 = 0.86 $$
$$ \frac{2}{7.31} \cdot 0 = 0 $$
Daher lautet der neue 2D-Vektor p1 = 0|0|0,8618
Jetzt muss man noch bedenken, dass bei der Darstellung in VB.Net das y nach unten positiv läuft. Für das y im Programm wird dann -z genommen! (In diesem Beispiel, es kann ja sein, dass die Achsen bei eurem Projekt anders sind).
Nun zum eigentlichen Thema „eine Ebene (im mathematischen Sinn) in 3D rotieren und auf 2D darstellen“
Ich komme direkt zum Punkt. Ich schaue hier in Draufsicht (also -z Richtung) auf die Situation. Man sieht die gemischt-gedrehte Ebene (20° um y und 10° um x). Diese hat dementsprechend die Parameterform
$$ E: \vec{x} = \left( \begin{array}{c} 0 \\\ 0 \\\ 0 \end{array}\right) + s \cdot \left( \begin{array}{c} 0.9396926 \\\ 0 \\\ -0,34202 \end{array}\right) + t \cdot \left( \begin{array}{c} 0 \\\ 0,9848 \\\ 0,173648 \end{array}\right) $$
Hier sieht auch wieder das „Fenster“ (auch wieder eine grüne Ebene). Dieses Fenster ist auf der Höhe z = 20; die Kamera sitzt über dem Ursprung und befindet sich auf der Höhe = 30,1. Nun werden die 4 Vektoren p1 bis p4 mit der oben genannten Formel berechnet. Hinweis: Da ich in Draufsicht auf die Szene schaue, kommt mir die blaue Ebene beim Drehen ja entgegen, also ist die einzusetzende Höhe
$$ \underbrace{30.1}_{Kamerahöhe} -(-|0.34202| \cdot 10+|0,1736| \cdot 10) $$
Die 10 dienen nur der Vergrößerung. Je nachdem, an welcher Ecke man ist, muss man die Minuszeichen durchtauschen, denn$\vec{p1}$soll immer links oben sein,$\vec{p2}$immer oben rechts,$\vec{p3}$unten rechts,$\vec{p4}$unten links - egal, wie die Ebene sich dreht.
Dies hab ich implementiert. Das Programm funktioniert, was die Mathematik angeht, korrekt.Ich muss nur noch die Fälle "beide Winkel negativ", "Winkel Phi positiv und Theta negativ" und"Winkel Phi negativ und Theta positiv"einbauen.Edit: Erledigt. Nun ist es so, dass diese darzustellende Ebene nunmal per Definition platt ist. Sie selbst hat keine Tiefe. Das macht den Anblick etwas ungewohnt schwierig, weil man beim Drehen keine Seite sieht.
Edit: 1) mit-projiziertes Gitternetz und 2) Normalenvektor hinzugefügt. 3) Asynchrone Berechnung. 4) Code vereinfacht.
Anbei der Code:
Class_Ebene_Mathematik2
Quellcode
- #Disable Warning IDE1006 ' Benennungsstile
- #Disable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
- Imports System.Windows.Media.Media3D
- Imports Microsoft.WindowsAPICodePack.Dialogs
- Imports Microsoft.VisualBasic.ControlChars
- Public NotInheritable Class Class_Ebene_Mathematik2
- Private ReadOnly Deu As New System.Globalization.CultureInfo("de-DE")
- ''' <summary>
- ''' In Längeneinheiten. Es wird ein Vergrößerungsfaktor benutzt, da die Vektoren anfangs nur Einsen haben.
- ''' </summary>
- Private enlargement_factor As Double ' wird in Form_neue_Ebene_erstellen zugewiesen.
- ' Alle verwendeten Benennungen und Rechnungen basieren auf folgender Vorzeichenkonvention, wie man sie auch in der Dokumentation sieht.
- ' +x nach rechts
- ' +y nach oben
- ' +z aus der Zeichenebene heraus (man schaut auf die Pfeilspitze der z-Achse; Draufsicht).
- ' Die Ebene, die immer als Beispiel genommen wurde, lag in der xy-Ebene. (0|0|0) + s·(1|0|0) + t·(0|1|0)
- ' Die um die y-Achse um 20° gedrehte Ebene ist laut Drehmatrix: (0|0|0) + s·(0,94|0|-0,342) + t·(0|1|0)
- ' Die um die x-Achse um 20° gedrehte Ebene ist laut Drehmatrix: (0|0|0) + s·(1|0|0) + t·(0|0,94|0,342)
- ' Beim Zeichnen ist der Koordinatenursprung in der Mitte der PictureBox.
- ' Da in VB.Net die y-Achse positiv nach unten gezählt wird, wird in den Rechnungen das Vorzeichen gewechselt.
- Private A0 As Vector3D
- ' →
- Private AB As Vector3D
- ' →
- Private AC As Vector3D
- ''' <summary>
- ''' Winkel für Drehung um die x-Achse in Grad.
- ''' </summary>
- Public Phi As Double '= 0.0
- ''' <summary>
- ''' Winkel für Drehung um die y-Achse in Grad.
- ''' </summary>
- Public Theta As Double '= 0.0
- ''' <summary>
- ''' Die Kamera hängt genau über dem Ursprung, auf einer bestimmten Höhe.
- ''' </summary>
- Private Kameraposition_z As Double = 40.0
- ' Die Vektoren p1, p2, p3 und p4 laufen von der Mitte des Fensters zu den 4 Ecken der Projektion.
- ' → → → →
- Private p1, p2, p3, p4 As PointF
- Public Koordinatenform As String = ""
- Private Fensterhoehe As Double = 20.0
- ''' <summary>
- ''' Hilfslinien / Gitternetz
- ''' </summary>
- Private Grid_vertical As List(Of PointF)
- Private Grid_horizontal As List(Of PointF)
- Private Normal_projected As PointF
- Private ReadOnly point_of_origin As New PointF(0.0F, 0.0F)
- Public Sub um_x_und_y_Achsen_drehen(ByVal dphi As Double, ByVal dtheta As Double)
- Phi += dphi
- If Phi = 90.0 OrElse Phi = (-90.0) Then
- Phi = 0.0
- End If
- Theta += dtheta
- If Theta = 90.0 OrElse Theta = (-90.0) Then
- Theta = 0.0
- End If
- 'Theta = (20.0) : Phi = (-10.0) : Kameraposition_z = 30.1 : enlargement_factor = 1.0
- ' Für die Drehung um die y-Achse:
- ' nimmt man die "Drehmatrix für y" * RV1
- ' cos(α) 0 sin(α) 1 cos(α)
- ' 0 1 0 * 0 = 0
- '-sin(α) 0 cos(α) 0 -sin(α)
- AB = New Vector3D(Math.Cos(Theta * Math.PI / 180.0), 0.0, -Math.Sin(Theta * Math.PI / 180.0))
- ' Für die Drehung um die x-Achse:
- ' nimmt man die "Drehmatrix für x" * RV2
- ' 1 0 0 0 0
- ' 0 cos(α) -sin(α) * 1 = cos(α)
- ' 0 sin(α) cos(α) 0 sin(α)
- AC = New Vector3D(0.0, Math.Cos(Phi * Math.PI / 180.0), Math.Sin(Phi * Math.PI / 180.0))
- erstell_Koordinatenform()
- ' ============================================================================================================
- ' DOKUMENTATION der Darstellungs-Fälle nach Reihenfolge.
- ' 1.) Darstellung, die nur eine positive oder negative Drehung um die y-Achse behandelt.
- ' 2.) Darstellung, die nur eine positive oder negative Drehung um die x-Achse behandelt.
- ' p1, p2, p3 und p4 bleiben allerdings an denselben Ecken wie vorher; das heißt, die Formeln sind vertauscht.
- ' Was bei "links unten" war, ist nun bei "links oben".
- ' 3.) gemischte Drehungen
- ' ============================================================================================================
- If Phi = 0.0 AndAlso (Theta >= -90.0 OrElse Theta <= 90.0) Then ' um y-Achse gedreht.
- nur_um_yAchse_drehen()
- ElseIf Theta = 0.0 AndAlso (Phi >= -90.0 OrElse Phi <= 90.0) Then ' um x-Achse gedreht.
- nur_um_xAchse_drehen()
- ElseIf Phi > 0.0 AndAlso Theta > 0.0 Then ' mixed rotation, both angles positive
- 'Debug.WriteLine(Math.Round(AB.X, 3).ToString() & " " & Math.Round(AC.Y, 3).ToString() & " " & Math.Round(AB.Z, 3).ToString() & " " & Math.Round(AC.Z, 3).ToString())
- p1 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- 'Debug.WriteLine("p2X = " & Math.Round(p2.X, 3).ToString() & "p2Y = " & Math.Round(p2.Y, 3).ToString())
- p3 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p4 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- ElseIf Phi > 0.0 AndAlso Theta < 0.0 Then
- p1 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p3 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p4 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- ElseIf Phi < 0.0 AndAlso Theta < 0.0 Then
- p1 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p3 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p4 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- ElseIf Phi < 0.0 AndAlso Theta > 0.0 Then
- p1 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 - Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p3 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (-Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p4 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * 10.0 + Math.Abs(AC.Z) * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- End If
- create_Grid()
- create_Normal()
- End Sub
- Private Sub create_Grid()
- Grid_vertical = New List(Of PointF)
- Dim aktueller_Punkt As PointF
- For x As Integer = 10 To -10 Step -1
- For y As Integer = 10 To -10 Step -1
- If Phi > 0.0 AndAlso Theta > 0.0 Then
- aktueller_Punkt = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- ElseIf Phi > 0.0 AndAlso Theta < 0.0 Then
- aktueller_Punkt = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- ElseIf Phi < 0.0 AndAlso Theta > 0.0 Then
- aktueller_Punkt = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- ElseIf Phi < 0.0 AndAlso Theta < 0.0 Then
- aktueller_Punkt = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- End If
- Grid_vertical.Add(aktueller_Punkt)
- Next
- Next
- '===========================================================================
- Grid_horizontal = New List(Of PointF)
- Dim aktueller_Punkt2 As PointF
- For y As Integer = 10 To -10 Step -1
- For x As Integer = 10 To -10 Step -1
- If Phi > 0.0 AndAlso Theta > 0.0 Then
- aktueller_Punkt2 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- ElseIf Phi > 0.0 AndAlso Theta < 0.0 Then
- aktueller_Punkt2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- ElseIf Phi < 0.0 AndAlso Theta > 0.0 Then
- aktueller_Punkt2 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- ElseIf Phi < 0.0 AndAlso Theta < 0.0 Then
- aktueller_Punkt2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AB.X * x * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - (Math.Abs(AB.Z) * CDbl(x) + Math.Abs(AC.Z) * CDbl(y))) * AC.Y * y * enlargement_factor)
- )
- End If
- Grid_horizontal.Add(aktueller_Punkt2)
- Next
- Next
- End Sub
- Private Sub create_Normal()
- Dim Normal As Vector3D = Vector3D.CrossProduct(AB, AC) * 10.0 * enlargement_factor
- Dim Normal_without_z As New Vector3D(Normal.X, Normal.Y, 0.0)
- Dim Angle As Double = Vector3D.AngleBetween(Normal, Normal_without_z)
- Dim vertical_height As Double = Normal_without_z.Length * Math.Tan(Angle * Math.PI / 180.0)
- 'Debug.WriteLine(Math.Round((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - vertical_height) * Normal.X, 0).ToString())
- Normal_projected = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / Math.Abs(Kameraposition_z - vertical_height) * Normal.X),
- CSng((Kameraposition_z - Fensterhoehe) / Math.Abs(Kameraposition_z - vertical_height) * Normal.Y)
- )
- 'Debug.WriteLine(Math.Round(Normal_projected.X, 1).ToString() & " " & Math.Round(Normal_projected.Y, 1).ToString())
- End Sub
- Private Sub unitV_2D()
- Normal_projected = New PointF(CSng(Normal_projected.X / Math.Sqrt(Math.Pow(Normal_projected.X, 2.0) + Math.Pow(Normal_projected.Y, 2.0))),
- CSng(Normal_projected.Y / Math.Sqrt(Math.Pow(Normal_projected.X, 2.0) + Math.Pow(Normal_projected.Y, 2.0))))
- End Sub
- Public Sub Paint(ByVal g As Graphics)
- If g Is Nothing Then Return
- g.TranslateTransform(CSng(FormMain.PictureBox1.Size.Width / 2.0), CSng(FormMain.PictureBox1.Size.Height / 2.0))
- g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
- g.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
- g.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
- g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
- Using GPath As New Drawing2D.GraphicsPath
- GPath.AddLine(p1, p2)
- GPath.AddLine(p2, p3)
- GPath.AddLine(p3, p4)
- GPath.AddLine(p4, p1)
- Using BrushLightBlue As New SolidBrush(Color.FromArgb(112, 200, 255))
- g.FillPath(BrushLightBlue, GPath)
- End Using
- End Using
- If Grid_vertical IsNot Nothing Then
- Using Pen_Gelb As New Pen(Color.FromArgb(217, 217, 0), 1.0F)
- For i As Integer = 0 To Grid_vertical.Count - 2 Step 1
- ' Diese If-Bedingung dient dazu, dass nicht Punkte von unten nach oben schräg durchverbunden werden. Es ist zwar ein Quick&Dirty-Workaround, aber es geht.
- ' Die einzelnen Punkte sind bereits richtig projiziert und sind in der List(of PointF) gespeichert. Es würde also wenig Sinn machen, ein gerades Gitternetz zu zeichnen und dieses dann zu verdrehen (engl.: skew).
- ' Ich mache es mir zu Nutze, dass y regelmäßig von einem negativsten Wert auf einen positivsten Wert springt (oder andersherum).
- If Not ((Grid_vertical(i).Y > 0.0F AndAlso Grid_vertical(i + 1).Y < 0.0F AndAlso Math.Abs(Grid_vertical(i).Y - Grid_vertical(i + 1).Y) > 10.0F) Xor
- (Grid_vertical(i).Y < 0.0F AndAlso Grid_vertical(i + 1).Y > 0.0F AndAlso Math.Abs(Grid_vertical(i).Y - Grid_vertical(i + 1).Y) > 10.0F)) Then
- g.DrawLine(Pen_Gelb, Grid_vertical(i), Grid_vertical(i + 1))
- End If
- Next
- End Using
- End If
- If Grid_horizontal IsNot Nothing Then
- Using Pen_Gelb As New Pen(Color.FromArgb(217, 217, 0), 1.0F)
- For i As Integer = 0 To Grid_horizontal.Count - 2 Step 1
- ' Diese If-Bedingung dient dazu, dass nicht Punkte von unten nach oben schräg durchverbunden werden. Es ist zwar ein Quick&Dirty-Workaround, aber es geht.
- ' Die einzelnen Punkte sind bereits richtig projiziert und sind in der List(of PointF) gespeichert. Es würde also wenig Sinn machen, ein gerades Gitternetz zu zeichnen und dieses dann zu verdrehen (engl.: skew).
- ' Ich mache es mir zu Nutze, dass y regelmäßig von einem negativsten Wert auf einen positivsten Wert springt (oder andersherum).
- If Not ((Grid_horizontal(i).X > 0.0F AndAlso Grid_horizontal(i + 1).X < 0.0F AndAlso Math.Abs(Grid_horizontal(i).X - Grid_horizontal(i + 1).X) > 10.0F) Xor
- (Grid_horizontal(i).X < 0.0F AndAlso Grid_horizontal(i + 1).X > 0.0F AndAlso Math.Abs(Grid_horizontal(i).X - Grid_horizontal(i + 1).X) > 10.0F)) Then
- g.DrawLine(Pen_Gelb, Grid_horizontal(i), Grid_horizontal(i + 1))
- End If
- Next
- End Using
- End If
- If Not Single.IsInfinity(Normal_projected.X) AndAlso
- Not Single.IsInfinity(Normal_projected.Y) AndAlso
- Normal_projected.X < 800.0F AndAlso
- Normal_projected.Y < 800.0F Then
- Using PenPink As New Pen(Color.FromArgb(255, 0, 144), 5.0F)
- Normal_projected.Y *= -1.0F
- g.DrawLine(PenPink, point_of_origin, Normal_projected)
- End Using
- End If
- End Sub
- Public Sub verschieben(ByVal MouseLocation As System.Drawing.Point)
- 'Hiermit wird die Ebene im Ganzen verschoben. Eigentlich wird nur MouseLocation.X - AB.X * enlargement_factor
- ' benutzt, aber weil in der Paint-Prozedur der Koordinatensystemursprung auf die Mitte der Picturebox gelegt
- ' wird, wird noch "- FormMain.PictureBox1.Size.Width / 2.0" benutzt.
- p4 = New PointF(CSng(MouseLocation.X - AB.X * enlargement_factor - FormMain.PictureBox1.Size.Width / 2.0),
- CSng(MouseLocation.Y + AC.Y * enlargement_factor - FormMain.PictureBox1.Size.Height / 2.0))
- p1 = New PointF(CSng(MouseLocation.X - AB.X * enlargement_factor - FormMain.PictureBox1.Size.Width / 2.0),
- CSng(MouseLocation.Y - AC.Y * enlargement_factor - FormMain.PictureBox1.Size.Height / 2.0))
- p2 = New PointF(CSng(MouseLocation.X + AB.X * enlargement_factor - FormMain.PictureBox1.Size.Width / 2.0),
- CSng(MouseLocation.Y - AC.Y * enlargement_factor - FormMain.PictureBox1.Size.Height / 2.0))
- p3 = New PointF(CSng(MouseLocation.X + AB.X * enlargement_factor - FormMain.PictureBox1.Size.Width / 2.0),
- CSng(MouseLocation.Y + AC.Y * enlargement_factor - FormMain.PictureBox1.Size.Height / 2.0))
- End Sub
- Public Sub change_Kamerahoehe(ByVal Hoehe As Double)
- Me.Kameraposition_z = Hoehe
- End Sub
- Public Sub change_Fensterhoehe(ByVal hoehe As Double)
- Me.Fensterhoehe = hoehe
- End Sub
- Private Sub nur_um_yAchse_drehen()
- 'Debug.WriteLine(Math.Round(AB.X, 3).ToString() & " " & Math.Round(AC.Y, 3).ToString() & " " & Math.Round(AB.Z, 3).ToString() & " " & Math.Round(AC.Z, 3).ToString())
- p1 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z + AB.Z * 10.0) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z + AB.Z * 10.0) * AC.Y * 10.0 * enlargement_factor))
- p2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - AB.Z * 10.0) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z + (-AB.Z) * 10.0) * AC.Y * 10.0 * enlargement_factor))
- 'Debug.WriteLine("p2X = " & Math.Round(p2.X, 3).ToString() & "p2Y = " & Math.Round(p2.Y, 3).ToString())
- p3 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z - AB.Z * 10.0) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z + (-AB.Z) * 10.0) * AC.Y * 10.0 * enlargement_factor))
- p4 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (Kameraposition_z + AB.Z * 10.0) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (Kameraposition_z + AB.Z * 10.0) * AC.Y * 10.0 * enlargement_factor))
- End Sub
- Private Sub nur_um_xAchse_drehen()
- 'Debug.WriteLine(Math.Round(AB.X, 3).ToString() & " " & Math.Round(AC.Y, 3).ToString() & " " & Math.Round(AB.Z, 3).ToString() & " " & Math.Round(AC.Z, 3).ToString())
- p1 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z + AC.Z * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z + AC.Z * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p2 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z + AC.Z * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng(-(Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z + AC.Z * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- 'Debug.WriteLine("p2X = " & Math.Round(p2.X, 3).ToString() & "p2Y = " & Math.Round(p2.Y, 3).ToString())
- p3 = New PointF(
- CSng((Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z - AC.Z * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z - AC.Z * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- p4 = New PointF(
- CSng(-(Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z - AC.Z * 10.0)) * AB.X * 10.0 * enlargement_factor),
- CSng((Kameraposition_z - Fensterhoehe) / (-(Kameraposition_z - AC.Z * 10.0)) * AC.Y * 10.0 * enlargement_factor))
- End Sub
- Private Sub erstell_Koordinatenform()
- Dim _N As Vector3D = Vector3D.CrossProduct(AB, AC)
- Dim _xMinusA0 As String
- Dim _yMinusA0 As String
- Dim _zMinusA0 As String
- If A0.X = 0.0 Then
- _xMinusA0 = "x"
- Else
- _xMinusA0 = "(x - " & A0.X.ToString(Deu) & ")"
- End If
- If A0.Y = 0.0 Then
- _yMinusA0 = "y"
- Else
- _yMinusA0 = "(y - " & A0.Y.ToString(Deu) & ")"
- End If
- If A0.Z = 0.0 Then
- _zMinusA0 = "z"
- Else
- _zMinusA0 = "(z - " & A0.Z.ToString(Deu) & ")"
- End If
- Koordinatenform = Math.Round(_N.X, 3).ToString(Deu) & " * " & _xMinusA0 & " + " & Math.Round(_N.Y, 3).ToString(Deu) & " * " & _yMinusA0 & " + " & Math.Round(_N.Z, 3).ToString(Deu) & " * " & _zMinusA0
- End Sub
- Public Sub neue_Ebene_erstellen()
- Using FNEE As New Form_neue_Ebene_erstellen
- If FNEE.ShowDialog() = DialogResult.OK Then
- A0 = New Vector3D(CDbl(FNEE.TextBox_A0_x.Text), CDbl(FNEE.TextBox_A0_y.Text), CDbl(FNEE.TextBox_A0_z.Text))
- AB = New Vector3D(CDbl(FNEE.TextBox_RV1_x.Text), CDbl(FNEE.TextBox_RV1_y.Text), CDbl(FNEE.TextBox_RV1_z.Text))
- AC = New Vector3D(CDbl(FNEE.TextBox_RV2_x.Text), CDbl(FNEE.TextBox_RV2_y.Text), CDbl(FNEE.TextBox_RV2_z.Text))
- enlargement_factor = CDbl(FNEE.TextBox_G.Text)
- End If
- End Using
- End Sub
- End Class
- #Enable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
und der Aufruf in Form1.vb
Spoiler anzeigen
VB.NET-Quellcode
- #Disable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
- Public NotInheritable Class FormMain
- Private ReadOnly Deu As New System.Globalization.CultureInfo("de-DE")
- Private program_has_finished_loading As Boolean '= False
- Private Ebene As Class_Ebene_Mathematik2
- Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- Me.Location = New System.Drawing.Point(0, 0)
- Label_Phi.Text = My.Resources.Phi_leer
- Label_Theta.Text = My.Resources.Theta_leer
- TextBox_Kamerahoehe.Text = My.Resources.vierzig
- TextBox_Fensterhoehe.Text = My.Resources.zwanzig
- End Sub
- Private Sub FormMain_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
- Ebene = New Class_Ebene_Mathematik2
- Ebene.neue_Ebene_erstellen()
- program_has_finished_loading = True
- End Sub
- Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
- If e.Button = MouseButtons.Left Then
- Ebene.verschieben(e.Location)
- PictureBox1.Invalidate()
- End If
- End Sub
- Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
- If e.Button = MouseButtons.Left Then
- Ebene.verschieben(e.Location)
- PictureBox1.Invalidate()
- End If
- End Sub
- Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
- If e.Button = MouseButtons.Left Then
- Ebene.verschieben(e.Location)
- PictureBox1.Invalidate()
- End If
- End Sub
- Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
- If Not program_has_finished_loading OrElse Ebene Is Nothing Then Return
- Ebene.Paint(e.Graphics)
- End Sub
- Private Async Sub FormMain_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
- Select Case e.KeyCode
- Case Keys.W
- Await Task.Run(Sub() Ebene.um_x_und_y_Achsen_drehen(-1.0, 0.0))
- TextBox_KF.Text = Ebene.Koordinatenform & " = 0"
- Label_Phi.Text = "ϕ = " & Math.Round(Ebene.Phi, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- Label_Theta.Text = "θ = " & Math.Round(Ebene.Theta, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- PictureBox1.Invalidate()
- Case Keys.S
- Await Task.Run(Sub() Ebene.um_x_und_y_Achsen_drehen(1.0, 0.0))
- TextBox_KF.Text = Ebene.Koordinatenform & " = 0"
- Label_Phi.Text = "ϕ = " & Math.Round(Ebene.Phi, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- Label_Theta.Text = "θ = " & Math.Round(Ebene.Theta, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- PictureBox1.Invalidate()
- Case Keys.A
- Await Task.Run(Sub() Ebene.um_x_und_y_Achsen_drehen(0.0, -1.0))
- TextBox_KF.Text = Ebene.Koordinatenform & " = 0"
- Label_Phi.Text = "ϕ = " & Math.Round(Ebene.Phi, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- Label_Theta.Text = "θ = " & Math.Round(Ebene.Theta, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- PictureBox1.Invalidate()
- Case Keys.D
- Await Task.Run(Sub() Ebene.um_x_und_y_Achsen_drehen(0.0, 1.0))
- TextBox_KF.Text = Ebene.Koordinatenform & " = 0"
- Label_Phi.Text = "ϕ = " & Math.Round(Ebene.Phi, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- Label_Theta.Text = "θ = " & Math.Round(Ebene.Theta, 0).ToString(Deu).PadLeft(2, "0"c) & " °"
- PictureBox1.Invalidate()
- Case Else
- Exit Select
- End Select
- End Sub
- Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
- Ebene.neue_Ebene_erstellen()
- End Sub
- Private Sub TextBox_Kamerahoehe_TextChanged(sender As Object, e As EventArgs) Handles TextBox_Kamerahoehe.TextChanged
- If Ebene IsNot Nothing Then
- Ebene.change_Kamerahoehe(CDbl(TextBox_Kamerahoehe.Text))
- End If
- End Sub
- Private Sub TextBox_Fensterhoehe_TextChanged(sender As Object, e As EventArgs) Handles TextBox_Fensterhoehe.TextChanged
- If Ebene IsNot Nothing Then
- If CDbl(TextBox_Fensterhoehe.Text) >= CDbl(TextBox_Kamerahoehe.Text) Then
- TextBox_Fensterhoehe.ForeColor = Color.Red
- Else
- TextBox_Fensterhoehe.ForeColor = Color.FromArgb(0, 138, 0) ' Mittelgrün
- Ebene.change_Fensterhoehe(CDbl(TextBox_Fensterhoehe.Text))
- End If
- End If
- End Sub
- End Class
- #Enable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
*sigh* ist also doch so eine Strahlensatzgeschichte... Im Grunde genommen hatte ich das fast mal so, aber ich habe nicht ein Fenster gehabt...
$ z_{neu} = \frac{d}{x} \cdot z $
Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „Bartosz“ ()
-
Benutzer online 1
1 Besucher
-
Ähnliche Themen
-
Form drehen (Norton,Kaspersky)
Gelöschter Benutzer - - Sonstige Problemstellungen
-
8 Benutzer haben hier geschrieben
- Bartosz (18)
- RodFromGermany (7)
- VB.neter0101 (3)
- Joshi (2)
- ErfinderDesRades (2)
- -Franky- (2)
- Fakiz (1)
- exc-jdbi (1)