AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Funktion graphisch aufzeichnen (Polarkoordinaten)
Thema durchsuchen
Ansicht
Themen-Optionen

Funktion graphisch aufzeichnen (Polarkoordinaten)

Ein Thema von Jakob Ullmann · begonnen am 21. Jun 2008
Antwort Antwort
Benutzerbild von Jakob Ullmann
Jakob Ullmann

Registriert seit: 17. Feb 2007
218 Beiträge
 
Lazarus
 
#1

Funktion graphisch aufzeichnen (Polarkoordinaten)

  Alt 21. Jun 2008, 22:42
Analog zu meinem Projekt JTM habe ich mich gefragt, wie ich in ein Polarkoordinatensystem zeichnen könnte. Die Lösung ist nicht so einfach wie bei einem kartesischen Koordinatensystem. Mein Lösungsansatz wäre der folgende:

Delphi-Quellcode:
var
  ...
  stepOne: Integer;
  oX, oY: Integer;
  wh: Integer; // wh = WidthHeight because it's the same
                // But we only want the smaller one, so we
                // save it in a variable that we don't always
                // have to ask for it.
Damit haben wir unsere Variablen. oX und oY sind jeweils origin-x und origin-y, also die Mitte in diesem Fall (genau gesagt der Koordinatenursprung). Mit StepOne wird der Abstand zwischen zwei Ticks festgelegt, wobei der numerische Abstand zwischen zwei Ticks immer 1 ist. Nun zeichnen wir erstmal das leere Koordinatensystem ohne Inhalt:

Delphi-Quellcode:
procedure TForm1.DrawPlot;
var
  x, y, i: Integer;
  _x, _y: Single;
  can: TMetafileCanvas;
begin
  try
    if Image1.Width > Image1.Height then
      wh := Image1.Height
    else wh := Image1.Width;
    Image1.Picture.Metafile.Width := wh;
    Image1.Picture.Metafile.Height := wh;
    can := TMetafileCanvas.Create(Image1.Picture.Metafile, 0);
    oX := wh div 2; // find the origin (x)
    oY := wh div 2; // find the origin (y)
    can.Pen.Color := clSilver;
    can.Pen.Style := psClear;
    can.Brush.Color := clWhite;
    can.Rectangle(0, 0, wh, wh);
    if Ring1.Checked then // draw the gray circle around the graph, as you
                              // can se it in most of the graphs you find.
    begin
      can.Pen.Style := psSolid;
      can.Ellipse(0, 0, wh, wh);
    end;
    can.Pen.Style := psSolid;
    can.Font.Name := 'Arial';
    can.Font.Size := 10;
    for x := -(wh div stepOne div 2) to (wh div stepOne div 2) do // Draw ticks
    begin
      can.Pen.Color := clBlack;
      can.MoveTo(oX + x * stepOne, oX - 2); // ticks on the x-axis
      can.LineTo(oX + x * stepOne, oX + 3);
      can.TextOut(oX + x * stepOne + 5, oX + 5, // draw the labels
                            IntToStr(x));
      can.MoveTo(oY - 2, oY + x * stepOne); // ticks on the y-axis
      can.LineTo(oY + 3, oY + x * stepOne);
      can.TextOut(oY + 5, oY + x * stepOne + 5, // draw the labels
                            IntToStr(x));
    end;
    can.MoveTo(0, oX); // The lines of the y- and x-axis
    can.LineTo(wh, oX);
    can.MoveTo(oY, 0); // the other line
    can.LineTo(oY, wh);
Bis dahin ist alles fröhliches Zeichnen ohne große Rechnerei. Ring1 ist bei mir ein Menu-Item, aber es kann genauso eine Checkbox oder ein Radiobutton (wobei das nicht sinnvoll wäre) sein. Wie der Name schon sagt, wird angegeben, ob man einen grauen Ring außen herum haben möchte. can ist als MetafileCanvas deklariert. Warum? Weil eine Vektorgraphik praktisch ist, wenn man Drucken möchte oder die Graphik verlustfrei ins Word kopieren möchte. Und da das für uns keine großen Umstände sind, lohnt es sich, von Anfang an mit Vektorgraphiken zu arbeiten. Nun kommt der Teil, der die Funktionen aufzeichnen:

Delphi-Quellcode:
    // No go through all items and draw them
    for i := 0 to ListBox1.Items.Count - 1 do
    begin
      Parser1.Expression := ListBox1.Items[i];
      Parser1.X := 0;
      try
        can.Pen.Color := StrToInt('$00'+Copy(ColorDialog1.CustomColors[i], 8, 6));
      except
        can.Pen.Color := clBlack;
      end;
      can.MoveTo(oX + round(cos(_x) * Parser1.Value * stepOne),
                 oY - round(sin(_x) * Parser1.Value * stepOne));
      for x := 1 to round(2 * Pi * 100) do
      begin
        _x := x / 100;
        Parser1.X := _x;
        can.LineTo(oX + round(cos(_x) * Parser1.Value * stepOne),
                            oY - round(sin(_x) * Parser1.Value * stepOne));
        can.MoveTo(oX + round(cos(_x) * Parser1.Value * stepOne),
                            oY - round(sin(_x) * Parser1.Value * stepOne));
      end;
    end;
  finally
    can.Free;
  end;
end;
Genau genommen ist es der zweite Teil der Prozedur DrawPlot, also mit Freigabe von can. Parser1 ist vom Typ TParser aus der Unit Parser10. Einfach mal bei torry.net nach "parser" suchen, dann wird man schnell fündig. Wenn man einen anderen Parser benutzt, einfach die entsprechenden Aufrufe ersetzen. Was die Eigenschaften bedeuten, sollte sich eigentlich von selbst erklären.
Jakob
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:37 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