Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Line mit Winkel zeichnen (https://www.delphipraxis.net/182237-line-mit-winkel-zeichnen.html)

Peter666 11. Okt 2014 13:00

Line mit Winkel zeichnen
 
Hi,

ich weiß die Frage sollte eigentlich ein 8te Klasse Schüler gelöst bekommen, aber irgendwie habe ich eine Blockade und ja mir ist klar das mir die Frage eigentlich etwas peinlich sein sollte.

Ich habe eine Line von Punkt P1 zu P2 und möchte jeweils am Punkt P1 bzw. P2 eine weitere Linke in einem Bestimmten Winkel zeichnen (in meinem Fall im 90° Winkel).
Die Endlinien besitzen eine Feste Länge.

Peter

Jens01 11. Okt 2014 15:05

AW: Line mit Winkel zeichnen
 
Vektorrechnung!
Ich nehme mal 2D an und dass eine Vektorlib vorhanden ist.
-Winkel der vorhandenen Linie ermitteln. Mit Skalarprodukt oder einfache Winkelrechnung.
-90 Grad zu dem Winkel addieren und die neue Linie entsprechend um den Ursprung rotieren lassen.
-Die Linie an den gewünschten Punkt verschieben. Beide Punkte der neuen Linie mit dem neuen Positionspunkt addieren.

Medium 11. Okt 2014 15:22

AW: Line mit Winkel zeichnen
 
Da hilft die gute alte Vektorrechnung. Für die Winkelstücke nimmst du einfach den Vektor von p1 nach p2 (oder umgekehrt) und drehst diesen um 90°. Das auf p1 und p2 addiert ergibt deine weiteren gesuchten Punkte.

Die Idee: Bei einem Vektor (x, y) ist 90° dazu (y, -x) und (-y, x). Man kommt da also komplett ohne Trigonometrie aus - sogar ohne Rechnen :) Diese müssen dann nur noch auf deine gewünschte Länge gebracht werden:
(v': Längenangepasster Vektor; L: Deine Ziellänge; v: Gedrehter Vektor (p1-p2))
Code:
         /        v.x        \
         | ----------------- |
         | sqrt(v.x² + v.y²) |
v' = L * |                   |
         |        v.y        |
         | ----------------- |
         \ sqrt(v.x² + v.y²) /
Und dann auf die Endpunkte addieren. Welche Richtung man nachher erhält hängt davon ab, wie rum man den Ausgangsvektor (p1-p2 oder p2-p1) bildet, und welche der beiden 90° Varianten man nimmt.

Peter666 13. Okt 2014 19:05

AW: Line mit Winkel zeichnen
 
Danke :) ja manchmal stellt man sich aber auch dumm an. Nun hab ich noch ein kleines anderes Problem. Ich hab ein Spielfeld von 4096x4096 Bildpunkten und möchte mit einem Skalierungsfaktor stets den Inhalt von der Spielfeldmitte auf mein frei vergrößerbares Anzeigefenster zeichnen.

Peter

Jens01 13. Okt 2014 23:22

AW: Line mit Winkel zeichnen
 
Bei Graphics32 gibts solche TImage-Komponenten, die skalieren können.
Ansonsten Vektorgraphik benutzen.

Bjoerk 14. Okt 2014 09:02

AW: Line mit Winkel zeichnen
 
Dann wir es vermutlich Zeit sich von den CanvasPixeln zu verabschieden und mm Werte zu verwenden? Ich würde die Objekte in mm speichern und ausrechnen, mit ppMM in CanvasPunkte umrechnen und auf eine Metafile zeichnen. Die Metafile dann mit StrechDraw in einer Paintbox anzeigen (so kann man auch bequem zoomen). Die Objekte zentriert zu platzieren ist gar nicht so leicht, aber auch nix weltbewegendes (Zusammenspiel von Grafik-Schwerpunkt und Canvas-Schwerpunkt). Zunächst brauchst du eine Entscheidung wo der Ursprung deines mm Koordinatensystems liegen soll. Gebräuchlich sind unten links (mmY nach oben positiv) und oben links (mmY nach unten positiv).

Peter666 14. Okt 2014 10:38

AW: Line mit Winkel zeichnen
 
Das Spielfeld ist ja kein Bild sondern ein Array aus den entsprechenden Tiles. Gezeichnet wird das ganze dann in etwa so: Display.DrawTile(X,Y,ScaleFactor,Tile);

Wobei der Scalefactor dann der Anzeigelogik sagt wie groß das Tile gezeichnet werden soll. Das komplett auf ein Bild zu malen wäre zu viel des Guten.

Peter

Bjoerk 14. Okt 2014 11:33

AW: Line mit Winkel zeichnen
 
Dann hast du es doch schon fast so? Was für ein Canvas meinst du mit Display? Ist das FMX Zeugs?

Peter666 14. Okt 2014 11:45

AW: Line mit Winkel zeichnen
 
Die Anzeige ist abstrakt gehalten. Das Spiel nutzt lediglich ein Interface das die Hauptanwendung für die Anzeige anbietet.
Die Spieleklasse bekommt die Größe des Anzeigefenster, weiß die Spielfeldgröße und soll stets anhand des Skalierungsfaktors einen Spielausschnitt zeichnen, wobei bei Faktor 1 das Spielfeld komplett im Fenster (unter Berücksichtigung des Bildseitenverhältnisses) angezeigt wird.

Mir schwebt so etwas vor:

Delphi-Quellcode:
TScaleScene = class
  protected
    FScale: integer;
    FScreenWidth: integer;
    FScreenHeight: integer;

    FMousePos: TPointF;
    FCameraPos: TPointF;
    FPreMovePos: TPointF;
  public
    constructor Create;
    procedure SetScreen(const AWidth, AHeight: integer);

    procedure DoMouseMove(const x, y: single; const ButtonA, ButtonB: Boolean);
    procedure DoMouseDelta(const Delta: Integer);
  end;

constructor TScaleScene.create;
begin
  FScale := 32;
  FCameraPos := PointF(0, 0);
  FPreMovePos := PointF(-1, -1);
end;

procedure TScaleScene.SetScreen(const AWidth, AHeight: integer);
begin
  FScreenWidth := AWidth;
  FScreenHeight := AHeight;
end;

procedure TScaleScene.DoMouseDelta(const Delta: Integer);
var cmx, cmy: single;
begin
  if (Delta <> 0) then
  begin
    cmx := FCameraPos.X / FScale;
    cmy := FCameraPos.Y / FScale;
    FScale := FScale - Delta;
    if (FScale < 16) then
      FScale := 16;
    if (FScale > 64) then
      FScale := 64;
    FCameraPos.X := trunc(cmx * FScale);
    FCameraPos.Y := trunc(cmy * FScale);
  end;
end;

procedure TScaleScene.DoMouseMove(const x, y: single; const ButtonA, ButtonB: Boolean);
var
  cmx, cmy: single;
begin
  if ButtonA then
  begin
    if (FPreMovePos.X <> -1) and (FPreMovePos.Y <> -1) then
    begin
      FCameraPos.X := FCameraPos.X - (x - FPreMovePos.X);
      FCameraPos.Y := FCameraPos.Y - (y - FPreMovePos.Y);
    end;
    FPreMovePos.X := x;
    FPreMovePos.Y := y;
  end
  else
  begin
    FPreMovePos.X := -1;
    FPreMovePos.Y := -1;
  end;

  if ButtonB then
  begin
    cmx := FCameraPos.X / FScale;
    cmy := FCameraPos.Y / FScale;
    FScale := 32;
    FCameraPos.X := trunc(cmx * FScale);
    FCameraPos.Y := trunc(cmy * FScale);
  end;

  if (FCameraPos.X < 0) then
    FCameraPos.X := 0;
  if (FCameraPos.Y < 0) then
    FCameraPos.Y := 0;
  if FCameraPos.X > FScreenWidth then
    FCameraPos.X := FScreenWidth;
  if FCameraPos.Y > FScreenHeight then
    FCameraPos.Y := FScreenHeight;

  FMousePos.X := FMousePos.X / FScale;
  FMousePos.Y := FMousePos.Y / FScale;
end;
Peter


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:58 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