Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Polygon drehen (https://www.delphipraxis.net/160409-polygon-drehen.html)

Peach 11. Mai 2011 18:19

Polygon drehen
 
Ich bräuchte bei meinem Delphi-Programm mal Hilfe!

Zum Programm: Es sollen Punkte auf dem Bildschirm markiert werden und daraus ein Polygonzug erstellt werden. Und der zweite Teil der Aufgabe besteht daraus diesen Polygonzug im Punkt 1 mit dem Winkel w zu drehen.

Die Sache mit dem Polygonzug habe ich hinbekommen, das stellte kein Problem dar. Nun dachte ich mir wegen den zweiten Teil der Aufgabe, dass ich die Punkte erstmal um den Ursprung verschiebe, sie neu zeichnen lasse und danach den Polygonzug wieder verbinde. Sollte das dann funktionieren würde ich es um den Punkt 1 drehen lassen.
Jedoch bekomme ich es einfach nicht hin, mir ist die geometrische Transformation schon bewusst und rein theoretisch ist mir das auch klar, aber ich bekomme es leider nicht umgesetzt. Ich hoffe ich bin nicht auf den Holzweg mit meiner Idee die Punkte zu "verschieben" und anschließend den Polygon neuzuzeichnen..:?:

Punkte für den Polygonzug setzen:
Delphi-Quellcode:
procedure TForm4.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   image1.Canvas.Pen.Color:=clblack;
   image1.Canvas.brush.Style:=bsclear;
if button=mbLeft then
begin
  n:=n+1;
    xp[n]:=x;
    yp[n]:=y;
    image1.Canvas.Rectangle(x-3,y-3,x+3,y+3);
end;
end;
Polygonzug verbinden:
Delphi-Quellcode:
procedure TForm4.Button1Click(Sender: TObject);
     var i:integer;
begin

   n:=n+1;
xp[n]:=xp[1];
yp[n]:=yp[1];
image1.canvas.moveto (xp[n],yp[n]);
for i:=n+1 to n-1 do


image1.Canvas.MoveTo(xp[i],yp[i]);
for i:=1 to n-1 do
image1.canvas.lineto (xp[i+1], yp[i+1]);


end;

Vielen Dank schonmal!!

Sinderion 11. Mai 2011 18:38

AW: Polygon drehen
 
Erst die Vektoren relativ zu dem Punkt ausrechnen, um den gedreht werden soll, also z.B:
Code:
P_relativ[i]:=P[i]-P1
Dann mit der Drehmatrix multiplizieren, war glaube ich:

Code:
M = (  Cos(alpha)  Sin(alpha) )
    (  -Sin(Alpha) Cos(Alpha) )
Also:
Code:
P_gedreht = M * P_relativ
So in etwa müsste es funktionieren.

Jens01 11. Mai 2011 21:21

AW: Polygon drehen
 
Das stammt aus meiner Sammlung :

Delphi-Quellcode:
RVektor = record
 x, y: Double;
end;
// WZ = Winkel

function Rotate(WZ : Double; Vektor : RVektor): RVektor;
begin
  result.x := Vektor.x * cos(degtorad(WZ)) - Vektor.y * sin(degtorad(WZ));
  result.y := Vektor.x * sin(degtorad(WZ)) + Vektor.y * cos(degtorad(WZ));
end;

jfheins 11. Mai 2011 21:54

AW: Polygon drehen
 
Zitat:

Zitat von Sinderion (Beitrag 1100259)
So in etwa müsste es funktionieren.

Nicht vergessen, die gedrehten vektoren wieder "zurückzuschieben" ;)

christopher85 30. Jun 2011 14:12

AW: Polygon drehen
 
Hallo! Ich habe die selbe Aufgabe, jedoch ein etwas anderes Problem!
der debugger zeigt mir eine fehlermeldung an: die dateitypen seien inkompatibel. ich soll es wohl als integer deklariert haben. jedoch wird der code in extendet gerechnet.

Zitat:

procedure TForm1.Button4Click(Sender: TObject);
begin
w:=spinedit1.value;
for i:=1 to n do
begin
u:=yp[n]*sin(w)+xp[n]+cos(w);
v:=yp[n]+cos(w)-xp[n]+sin(w);
// und zwar will ich in dem oberen programmstück die koorinaten eines Punktes errechnen. dazu nehme ich den winkel aus einer spinedit.

Zitat:

var u,v,y,x,n,i:integer;
w:extended;
xp,yp:array[1..100]of integer;
// meine variablendeklaration sieht dann ungefähr so aus. dachte mir, da ich W vorher als integer deklariert hatte, mach ich daraus extendet. ich kann mir vorstellen, dass nachkommawerte bei der rechnung mit cosinus und sinus rauskommen. aber wie kann ich das in der variablendeklaration ermöglichen?

blackfin 30. Jun 2011 14:18

AW: Polygon drehen
 
Zitat:

aber wie kann ich das in der variablendeklaration ermöglichen?
Delphi-Quellcode:
var
u,v,y,x,w: double; // oder single / extended / real
n,i:integer; // i ist eine schleifenvariable, also integer. n anscheinend auch. aber wo wird die gesetzt? in deinem code nicht...
xp,yp:array[1..100]of integer; // wenn das auch zahlen mit nachkommastellen sein können, dann auch hier double / single / extended / real...

oder ich versteh nicht, wo nun das problem sein soll?

Edit: Noch was zum Unterschied der Fliesskomma-Typen:

Single
Genauigkeit: 7–8 Nachkommastellen , Speichergrösse: 4 Byte

Double / Real
Genauigkeit: 15–16 Nachkommastellen , Speichergrösse: 8 Byte

Extended
Genauigkeit: 19–20 Nachkommastellen , Speichergrösse: 10 Byte

shmia 30. Jun 2011 14:59

AW: Polygon drehen
 
Siehe auch Code-Library: Verschiebung und Drehung im 2D Raum

Bjoerk 30. Jun 2011 15:23

AW: Polygon drehen
 
Wenn x und y integer sind, ist es folgerichtig, wenn u und v auch integer sind.
x,y,u,v: array [1..100] of integer;
Delphi-Quellcode:
Procedure Transformiere (const x,y: integer; w: double; var u,v: integer);
begin
  w:= w * 3.1416/180;
  u := Round(  x * cos (w) + y * sin(w));
  v := Round( -x * sin (w) + y * cos(w));
end;
Delphi-Quellcode:
  for i := 1 to n do
    Transformiere (x[i], y[i], spinedit1.value, u[i], v[i]);

Wenn x und y double sind, ist es folgerichtig, wenn u und v auch double sind.
x,y,u,v: array [1..100] of double;
Delphi-Quellcode:
Procedure Transformiere (const x,y: double; w: double; var u,v: double);
begin
  w:= w * 3.1416/180;
  u :=  x * cos (w) + y * sin(w);
  v := -x * sin (w) + y * cos(w);
end;
Delphi-Quellcode:
  for i := 1 to n do
    Transformiere (x[i], y[i], spinedit1.value, u[i], v[i]);

shmia 30. Jun 2011 16:11

AW: Polygon drehen
 
@Bjoerk ich würde die Prozedure nicht "Transformiere" sondern "Rotiere" nennen.
Aber ich möchte doch nochmal auf meinen vorherigen Beitrag verweisen.
Eleganter kann man es eigentlich nicht programmieren.
Das es sich bei Rotate2D und Translate2D um Funktionen handelt, kann man sie problemlos verketten:
Delphi-Quellcode:
// verschieben, drehen um 45 Grad und zurückverschieben
NeuPunkt := Translate2D(Rotate2D(Translate2D(orgPunkt, P2), DegToRad(45.0)), invP2);
Durch die Verwendung des Records TPoint wird der Code leichter lesbar.
Bleibt man bei x und y, braucht man doppelt so viele Variablen.

Man kann aus den Verschiebungen und Drehungen auch eine Transformationsmatrix berechnen.
Dann kann man diese Transformationsmatrix auf alle Punkte anwenden und spart so Rechenzeit. Dafür ist dann die nötige Mathematik etwas aufwändiger.

christopher85 30. Jun 2011 17:26

AW: Polygon drehen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Guten Abend!

Also im Anhang habe ich mal einen Screenshot angehängt. In ihm sieht man halt unten in dieser Berichtigungszeile, dass inkompatible Typen auftreten.

Und zwar in den Zeilen vom Code:

Delphi-Quellcode:
w:=spinedit1.value;
for i:=1 to n do
  begin
    u:=yp[n]*sin(w)+xp[n]+cos(w);
    v:=yp[n]+cos(w)-xp[n]+sin(w);
Ich habe dann natürlich erstmal gegoogelt was das bedeutet. Weiss da aber irgendwie nicht weiter.

Das ist aber nur mein Teilproblem. Außerdem weiss ich nicht wie ich die Kooridanten u und v wieder in das array bekommen soll (für alle anderen punkte) und deses dann wieder zeichnen soll. Aber das ist erstmal ein anderer Schuh.

EDIT: also ich muss sagen, dass ich ecuh n bissl bewundere. ich schu mir gerade so die angebotenen quelltexte an und finde es ziemlich kompliziert sich in andere quelltexte reinzufuchsen. auch wegen der unterschiedlich definierten variablen.

jaenicke 30. Jun 2011 17:35

AW: Polygon drehen
 
Zitat:

Zitat von christopher85 (Beitrag 1109304)
In ihm sieht man halt unten in dieser Berichtigungszeile, dass inkompatible Typen auftreten.

Weil dein u und v Integervariablen sind, bei der Berechnung aber keine ganzen Zahlen herauskommen. Also deklariere die als Single oder Double oder du musst mit Round runden.

Nebenbei hast du aus Versehen i global deklariert, daher die Warnung, Variablen sollten nach Möglichkeit lokal in der Prozedur deklariert werden...

Zitat:

Zitat von blackfin (Beitrag 1109248)
Extended
Genauigkeit: 19–20 Nachkommastellen , Speichergrösse: 10 Byte

Wobei man Extended nicht mehr benutzen sollte. Die Berechnungen sind damit relativ aufwendig, da diese ohne Coprozessor mit der Prozessorarchitektur nicht abgebildet werden können. Zudem ist man damit auf eine Plattform festgelegt, wie auch im Wiki schon steht:
http://docwiki.embarcadero.com/VCL/en/System.Extended

Deshalb sollte man Single oder Double benutzen.

christopher85 30. Jun 2011 18:31

AW: Polygon drehen
 
Super! Dank Dir Jaenicke!

Nun stellt sich mir noch die Frage wie ich u und das dazugehörige v als Koordinaten wieder als Punkt zeichnen kann.
xp[u] und yp[v].

Weil ja durch diese for-Schleife u und v innerhalb kurzer Zeit wieder überschrieben werden. Also muss ich ja innerhalb dieser for-Schleife die Punkte schon zeichnen lassen.

Also mal für mich so zur Chronologie:
//erst die Punktkooridnaten berechnen
Delphi-Quellcode:
u:=yp[n]*sin(w)+xp[n]+cos(w);
    v:=yp[n]+cos(w)-xp[n]+sin(w);
//dann vermutlich in die Matrix einfügen
u:=xp[n] v:=yp[n] :?: sry. bin da geistig nackig :lol:
//dann vielleicht das spiel mit der Polygonverbindung von Anfang an
if n=1 then image1.Canvas.MoveTo(x,y) ;
image1.Canvas.LineTo(xp[n],yp[n]);


EDIT: was mir gerade noch einfällt: ist es nicht doof Nachkommastellen für ein Canvasarray zu verwenden. das nimmt doch sicherlich nur ganzzahlige Werte, oder?

christopher85 1. Jul 2011 08:59

AW: Polygon drehen
 
Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
begin
w:=spinedit1.value;
w:=w*Pi/180;
for n:=1 to n-1 do
  begin
    u:=trunc((xp[1]-x)*cos(w)+(yp[1]-y)*sin(w));
    v:=trunc(-(xp[1]-x)*sin(w)+(yp[1]-y)*cos(w));
    image1.Canvas.Pixels[u,v]:=clgreen;
    image1.Canvas.Pen.Color:=clgreen;
    image1.Canvas.Ellipse(u-6,v-6,u+6,v+6);
also bis jetzt macht er mir eine drehunng um den koordinatenursprung. aber ich will ja eigentlich um punkt eins drehen. dazu muss man den abstand von punkt eins zur x und y achse von allen anderen punkten subtrahieren. frage mich aber wie ich das in den quelltext bekommen soll.

Memnarch 1. Jul 2011 09:59

AW: Polygon drehen
 
satz des pythagoras wäre möglich.

Distans zweier punkte ist:

Distanz = wurzel((|X1 - X2|)^2 + (|Y1 - Y2|)^2)

| = Betragszeichen. bedeutet es wird immer der absolute wert genommen(-2 wird zu 2)

Da gibts aber noch andere formeln um das umzusetezn, die ich auch glat für performanter halten würde...mir aber gerade nicht einfallen :D

EDIT: Betrags striche können weg, wird ja quadriert.

christopher85 1. Jul 2011 10:54

AW: Polygon drehen
 
Hi! Also hier mal der Fertige Quelltext zum Programm: dürfte so laufen. man sollte aber bevor man unterschiedliche winkel ausprobiert immer wieder neu zeichnen weil die variablendeklaration sich in "drehen" überschneidet!vor dem freien verwenden für belege immer wieder n stoßgebet zu meinem dank hinterlassen. dank an das delphiforum


Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Spin;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Label2: TLabel;
    SpinEdit1: TSpinEdit;
    procedure Button3Click(Sender: TObject);
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation
var p,q,u,v,y,x,n,i:integer;
xp,yp:array[1..100]of integer;
w:extended;


{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
if n>1 then
  begin
    image1.Canvas.LineTo(xp[1],yp[1]);


  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
image1.Canvas.brush.Style:=bssolid;
image1.Canvas.Pen.Color:=clwhite;
image1.Canvas.Rectangle(0,0,image1.Width,image1.Height);
image1.Canvas.Pen.Color:=clblack;
n:=0

end;

procedure TForm1.Button3Click(Sender: TObject);
begin
close;
end;


procedure TForm1.Button4Click(Sender: TObject);
var i:integer;
begin
w:=spinedit1.value;
w:=w*Pi/180;
for n:=1 to n do
  begin
    u:=trunc((xp[n]-xp[1])*cos(w)+(yp[n]-yp[1])*sin(w))+xp[1];
    v:=trunc(-(xp[n]-xp[1])*sin(w)+(yp[n]-yp[1])*cos(w))+yp[1];
    image1.Canvas.Pixels[u,v]:=clgreen;
    image1.Canvas.Pen.Color:=clgreen;
    image1.Canvas.Ellipse(u-6,v-6,u+6,v+6);
    xp[n]:=u;
    yp[n]:=v;

  end;
 image1.Canvas.moveto(xp[1],yp[1]);
  for i := 2 to n-1 do

 image1.Canvas.lineto(xp[i],yp[i]);
           image1.Canvas.lineto(xp[1],yp[1]);
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if button=mbleft then
    begin
      n:=n+1;
      xp[n]:=x;
      yp[n]:=y;
      image1.Canvas.Rectangle(x-3,y-3,x+3,y+3);
      if n=1 then image1.Canvas.MoveTo(x,y);
      end;
      begin



      image1.Canvas.LineTo(xp[n],yp[n]);
        end;
     if button=mbright then
      begin
        image1.canvas.lineto(xp[1],yp[1]);
      end;
end;

end.

blackfin 1. Jul 2011 11:26

AW: Polygon drehen
 
Nur so als kleiner Tipp:
Wenn du uns das Programm zum Testen / Ansehen zur Verfügung stellen willst, dann ist es meist besser, die Projektdateien ohne die compilierte EXE gezippt an einen Beitrag anzuhängen, anstatt nur den Code der Main-Unit zu posten, denn das Formular müsste man ja so auch noch manuell erstellen :-)

gammatester 1. Jul 2011 11:39

AW: Polygon drehen
 
Dein Code in TForm1.Button4Click transformiert den ersten Punkt in den Ursprung. Ist das gewollt oder ein Bug? Wenn nicht, nimm eine for-Schleife die bei 2 startet.Übrigens ist die Konstruktion
Delphi-Quellcode:
for n:=1 to n do
mM sehr unschön, warum nimmst Du nicht
Delphi-Quellcode:
for i:=1 to n do
?

Memnarch 1. Jul 2011 14:50

AW: Polygon drehen
 
@gammatester:

Delphi-Quellcode:
for N := 1 to N do
Also wenn ich von N zu N gehe machst doch immer genau einen schritt o.O

christopher85 1. Jul 2011 16:32

AW: Polygon drehen
 
Also das mit dem i=2 ist vermutlich im eifer des Gefechtes da reingerutscht. Mein letztes Problem war das gedrehte Polygon wieder mit linien zu verbinden. Das Programm hat aber immer das letzte ausgelassen. Konnte mir dann kaum noch etwas erklären und hab dann allesmöglich versucht.
Die Projektdateien kann ich leider erst am Monat anhängen, da ich mich jetzt nichtmehr in der Hochschule befinde.sry

Edit:(((Das mit dem trunc funktioniert aber dennoch, oder?)))


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz