![]() |
Optische Verkürzung
Hallo.
Erstmal vorweg: Mein Problem ist mathematisch. Und Zwar möchte ich auf ein Image mit Canvas ein Schachbrett zeichnen, allerdings optisch 3 Dimensional. Jetzt hab ich aber Probleme mit dem Faktor, um den der Y-Wert abnimmt, wenn man in die Tiefe geht. Mein Ansatz:
Delphi-Quellcode:
Allerdings bekomme ich beim Ausführen eine Fehlermeldung mit dem Inhalt: "ungültige Gleitkommaoperation". Soweit ich weiß heist das ja, dass ich durch 0 teilen würde oder eine Variable nicht richtig initialisiert worden ist.
Procedure TForm1.Gitter;
var i:Integer; a,b,a1,b1,x,y:Extended; begin Image.Canvas.Pen.Color := rgb(0, 0, 0); b := Image.Width; a := 1/2 * sqrt(power(Image.Height,2) + power((1/2 * Image.Width),2)); for I := 0 to 10 do begin Image.Canvas.MoveTo(i * round(b / 10), Image.Height); Image.Canvas.LineTo(round(I * b / 20 + Image.Height / 4), round(Image.Height / 2)); end; for I := 0 to 10 do begin x := 1/2 * (Image.Width - b); b1 := b / 10; a1 := a * (x / b); y := sqrt(power(a1,2) - power((1/2 * x),2)); Image.Canvas.MoveTo(round(x),round(Image.Height - y)); Image.Canvas.LineTo(Image.Width, round(Image.Height - y)); b := b - b1; a := a - a1; end; end; Ich wäre dankbar für einen Lösungsvorschlag oder verbesserung des Ansatzes. MFG |
Re: Optische Verkürzung
Das Problem ist diese Zeile
Delphi-Quellcode:
Je nach Größe des Images wird power((1/2 * x),2) größer als power(a1,2), so dass Du die Wurzel aus einer negativen Zahl ziehst
y := sqrt(power(a1,2) - power((1/2 * x),2));
|
Re: Optische Verkürzung
Ich würde an das Problem folgendermaßen drangehen (hab im Moment übrigens ein sehr ähnliches Problem, nur ohne Schachbrett)
1. Trapezverzerrung (damit die Linien zu einem Fluchtpunkt zusammenlaufen) 2. Drehung um die waagerechte Achse, sodass die Ebene schief im Raum liegt. 3. Parallelproketion, um wieder ein 2-dimensionales Bild zu bekommen Die ersten beiden Schritte sollten auch vertauschbar sein. Jetzt ist da natürlich erstmal die Frage, ob du dir was darunter vorstellen kannst :stupid: |
Re: Optische Verkürzung
Liste der Anhänge anzeigen (Anzahl: 1)
Erst einmal Danke für die Antworten.
Die Sache wird wohl etwas komplizierter, als ich angenommen habe :? ... Zitat:
|
Re: Optische Verkürzung
Liste der Anhänge anzeigen (Anzahl: 1)
Hab dir da mal was gecodet
Ist jetzt zwar Q&D und es hat auch ein bisschen gedauert bis das einigermaßen hingehauen hat - aber es dürfte deinen Anforderungen schon nahe kommen ;)
Code:
Der ober Schieber steuert die "Drehung" und der untere steuert die Trapezverzerrung. Um eine ordentliche Perspektive hinzubekommen müssen diese beiden passend gekoppelt sein. Hab das jetzt einfach mal probiert (wenn man den oberen Schiber bewegt, wird der untere auch angepasst)
using System;
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Test_1 { public partial class Form1 : Form { RectangleF Outline; byte Rows = 8; byte Cols = 8; Pen pen; public Form1() { InitializeComponent(); pen = new Pen(Color.Black, 2); Outline = new RectangleF(-200, 0, 400, 400); } private PointF DisplayTransform(PointF coord) { PointF Result = new PointF(); Result.X = coord.X + pictureBox1.Width / 2; Result.Y = coord.Y + pictureBox1.Height * 0.8f; return Result; } private PointF Transform(PointF coord) { // Trapezverzerrung coord.X = coord.X * ( 1 - coord.Y * ((float)trackBar3.Value / 10000f)); // Rotation um die x-Achse // gleichzeitug: Parallelprojektion // (Im Grunde geht man kurz in den 3D-Raum um dann die Z-Komponente wegzuwerfen, // da kann man sich die aber auch direkt sparen) coord.Y = coord.Y * (float)Math.Sin(trackBar1.Value * Math.PI / 180); return coord; } private void Transform(ref PointF[] coords) { for (int i = 0; i < coords.Length; i++) { coords[i] = DisplayTransform(Transform(coords[i])); } } private void pictureBox1_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; float colwidth = Outline.Width / (float)Cols; float rowheight = Outline.Height / (float)Rows; PointF[] Feld = new PointF[4]; Brush farbe; for (int row = 0; row < Rows; row++) { for (int col = 0; col < Cols; col++) { var left = Outline.Left + col * colwidth; var top = Outline.Top + row * rowheight; Feld[0] = new PointF(left, top); Feld[1] = new PointF(left + colwidth, top); Feld[2] = new PointF(left + colwidth, top + rowheight); Feld[3] = new PointF(left, top + rowheight); Transform(ref Feld); if ((row + col + 1) % 2 == 0) farbe = Brushes.Black; else farbe = Brushes.White; e.Graphics.FillPolygon(farbe, Feld); } } Feld[0] = new PointF(Outline.Left, Outline.Top); Feld[1] = new PointF(Outline.Left + Outline.Width, Outline.Top); Feld[2] = new PointF(Outline.Left + Outline.Width, Outline.Top + Outline.Height); Feld[3] = new PointF(Outline.Left, Outline.Top + Outline.Height); Transform(ref Feld); e.Graphics.DrawPolygon(pen, Feld); } private void trackBar1_Scroll(object sender, EventArgs e) { var a = 10 * Math.Cos((360 - trackBar1.Value) * Math.PI / 180); trackBar3.Value = (int)a; pictureBox1.Invalidate(); } private void trackBar3_Scroll(object sender, EventArgs e) { pictureBox1.Invalidate(); } private void Form1_SizeChanged(object sender, EventArgs e) { pictureBox1.Invalidate(); } } } Programm im Anahng ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz