TFPCustomCanvas Arc Methode, Verständnisfrage

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mario Peters
Beiträge: 9
Registriert: Sa 26. Apr 2025, 22:41

TFPCustomCanvas Arc Methode, Verständnisfrage

Beitrag von Mario Peters »

Hallo,

Ich sehe zwei Arc Methoden

die erste: Arc(left,top,right,bottom, Angle16Deg,Angle16DegLength: Integer);

die zweite: Arc(left,top,right,bottom,SX,SY,EX,EY: integer);

Welche Bedeutung haben in der zweiten Methode die Parameter SX,EX,SY,EY???

Sollten das in diesem Fall die Schnittpunkte des Bogens mit dessenn Enden sein, wie berechne ich die dann?

Ich habe folgende Ellipsengleichung:

Code: Alles auswählen

procedure PaintEllipse(Canv: TFPCustomCanvas; xm, ym, xR, yR, stangle, endangle: Extended; numSteps: Integer; c: TFPColor);
   var
    t, tStart, tEnd, tStep: Extended;
    i,j: Integer;
    x, y: Extended;
    MyPutPix: TPutPixelProc;

  procedure DrawPixel(Canv: TFPCustomCanvas; x,y: Longword);
  begin
      //für meine Frage uninteressant
  end;

 begin
      if numSteps < 1 then Exit; // Sicherheitsprüfung

      // Winkel in Radiant umrechnen
      tStart := DegToRad(stangle);
      tEnd := DegToRad(endangle);

      // Normierter Parameter t von tStart bis tEnd
      tStep := (tEnd - tStart) / numSteps;

      with canv.pen do
        case mode of
          pmMask : MyPutPix := @PutPixelAnd;
          pmMerge : MyPutPix := @PutPixelOr;
          pmXor : MyPutPix := @PutPixelXor;
        else MyPutPix := @PutPixelCopy;
      end;


      // Zeichne Punkte entlang der Ellipse
      for i := 0 to numSteps do
      begin
        t := tStart + i * tStep;
        // Parametrische Darstellung der Ellipse
        x := xm + xR * Cos(t); if t=tStart  then xs:=x; if t=tEnd then xe:=x; //ist das richtig, dann hätte ich die Positionen von SX,SY,EX,EY
        y := ym + yR * Sin(t); if t=tStart  then ys:=y; if t=tEnd then ye:=y;
        DrawPixel(Canv, Round(x), Round(y)); // Zeichne Pixel

      end;
   end;

Dann aber müsste ich dies Parameter umständlich vorher berechnen, wenn ich diese Methode benutzen will. Gibt es eine elegantere Berechnungsmrthode dafür oder interpretiere ich SX,SY,EX,EY ohnehin falsch? Leider sind diese Parameter in der FPCanvas Doku auch nicht erklärt

wp_xyz
Beiträge: 5218
Registriert: Fr 8. Apr 2011, 09:01

Re: TFPCustomCanvas Arc Methode, Verständnisfrage

Beitrag von wp_xyz »

Nein, das ist einfach nur irgendein Punkt in der Ebene. Es wird intern der Mittelpunkt der Ellipse mit diesem Punkt verbunden, und dort, wo die Linie die Ellipse schneidet, beginnt/endet der Bogen; die Rechnung muss du selbst nicht ausführen.

Das ist wahrscheinlich deswegen so gemacht, weil mit diesen Argumenten die Endpunkte klar definiert sind. Nimmt man dagegen die andere Variante mit den Winkel, ist unklar welcher Winkel gemeint ist. Ist es der Winkel, den so eine Verbindungslinie mit der x-Achse hat? Oder ist es der Winkel in den Ellipsengleichungen x = a * cos(phi), y = b * sin(phi)? Beide sind nicht identisch! Ich habe dazu vor kurzem einen Bug bearbeitet (https://gitlab.com/freepascal.org/lazar ... sues/41748), in dem sich eine Inkonsistenz der Arc-Methode zwischen win32 und den Linux-Widgetsets herausgestellt hat. In Laz/main wird künftig die zweite Definition (die mit den Ellipsengleichungen) verwendet.

Mario Peters
Beiträge: 9
Registriert: Sa 26. Apr 2025, 22:41

Re: TFPCustomCanvas Arc Methode, Verständnisfrage

Beitrag von Mario Peters »

Danke für die schnelle Antwort. Habe mir die .zip Datei runter geladen aber eine Frage ist noch offen:

So wie ich das verstehe, sind die Punkte SX,SY,EX,EY bisher beliebige Punkte der Ebene gewesen, deren Verbindungslinie vom Mittelpunkt der Ellipse zum Schnittpunkt Ellipse Verbindungslinie Mittelpunkt<-> Schnittpunkt auch diese Pukte SX,SY,EX,EY schnneiden, Nun aber sind das keine beliebigen Ounkte mehr sondern werden nach der Ellipsengleichung berechnet. Also wie in der von mir aufgeführten Methode. Da tritt aber ein neues Problem auf. wie kommt der Multiplikator 1000 zustande? C ist nach meinem Verständnis der Mittelpunkt der Ellipse ,P1, P2, die beiden Schnittpunkte mit der Ellipse, bei mie SX,SY,EX und EY und damit Endpunkte des Bogens. Warum aber muss da der Multiplikator, hier 1000 hinzugefügt werden? Warum gerade die 1000? ist das sowas wie in meiner Version die Anzahl der Steps?

Und unten in der PaintBox der Summand +/-5 ist mir in der Bedeutung auch unklar. Oder ist das eine Linienstärke?

Hier:

Code: Alles auswählen

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  R: TRect;
  C, P1, P2: TPoint;
  phi1, phi2: Double;
begin
  R := Rect(10, 10, 210, 110);
  C := Point((R.Left + R.Right) div 2, (R.Top + R.Bottom) div 2);

  Paintbox1.Canvas.Brush.Style := bsClear;
  Paintbox1.Canvas.Pen.Style := psDash;
  Paintbox1.Canvas.Pen.Color := clSilver;
  Paintbox1.Canvas.Rectangle(R);

  Paintbox1.Canvas.Pen.Style := psSolid;
  Paintbox1.Canvas.Pen.Color := clRed;
  Paintbox1.Canvas.Brush.Color := clRed;
  {$IFDEF FPC}
  if RadioButton2.Checked or RadioButton3.Checked then
    Paintbox1.Canvas.RadialPie(R.Left, R.Top, R.Right, R.Bottom, Scrollbar1.Position * 16, Scrollbar2.Position * 16);
  if RadioButton1.Checked or RadioButton3.Checked then
  begin
    Paintbox1.Canvas.Pen.Color := clBlue;
    Paintbox1.Canvas.Pen.Width := 3;
    Paintbox1.Canvas.Arc(R.Left, R.Top, R.Right, R.Bottom, Scrollbar1.Position * 16, Scrollbar2.Position * 16);
    Paintbox1.Canvas.Pen.Width := 1;
  end;
  {$ELSE}
  phi1 := Scrollbar1.Position * pi/180;
  phi2 := (Scrollbar1.Position + Scrollbar2.Position) * pi/180;
  P1 := C + Point(round(cos(phi1) * 1000), round(-sin(phi1) * 1000));
  P2 := C + Point(round(cos(phi2) * 1000), round(-sin(phi2) * 1000));
  Paintbox1.Canvas.Arc(R.Left, R.Top, R.Right, R.Bottom, P1.X, P1.Y, P2.X, P2.Y);
  {$ENDIF}

  // Draw angle lines (lines from center to far-away point in direction defined by angle w.r.t x axis)
  phi1 := Scrollbar1.Position * pi/180;
  phi2 := (Scrollbar1.Position + Scrollbar2.Position) * pi/180;
  P1 := C + Point(round(cos(phi1) * 1000), round(-sin(phi1) * 1000));
  P2 := C + Point(round(cos(phi2) * 1000), round(-sin(phi2) * 1000));
  Paintbox1.Canvas.Pen.Color := clSilver;
  Paintbox1.Canvas.MoveTo(C.X, C.Y);
  Paintbox1.Canvas.LineTo(P1.X, P1.Y);
  Paintbox1.Canvas.MoveTo(C.X, C.Y);
  Paintbox1.Canvas.LineTo(P2.X, P2.Y);

  // Calculate ellipse points (points on ellipsis at angles)
  P1 := Point(round(cos(phi1) * ((R.Right - R.Left) div 2)) + C.X, round(-sin(phi1) * ((R.Bottom - R.Left) div 2)) + C.Y);
  P2 := Point(round(cos(phi2) * ((R.Right - R.Left) div 2)) + C.X, round(-sin(phi2) * ((R.Bottom - R.Left) div 2)) + C.Y);
  Paintbox1.Canvas.Brush.Style := bsSolid;
  Paintbox1.Canvas.Brush.Color := clWhite;
  Paintbox1.Canvas.Ellipse(P1.X - 5, P1.Y - 5, P1.X + 5, P1.Y + 5);
  Paintbox1.Canvas.Ellipse(P2.X - 5, P2.Y - 5, P2.X + 5, P2.Y + 5);

end;

wp_xyz
Beiträge: 5218
Registriert: Fr 8. Apr 2011, 09:01

Re: TFPCustomCanvas Arc Methode, Verständnisfrage

Beitrag von wp_xyz »

Du beziehst dich auf das "arc_radialpie.zip"-File? Der Faktor 1000 ist der Abstand der Punkte (SX,SY) und (EX,EY) vom Ellipsenmittelpunkt; der Wert ist völlig egal, er sollte nur nicht zu klein sein, weil der Abstand ja mit sin und cos des Winkels multipliziert wird, und da erhält man nach dem Runden auf Integer bei zu kleinem Abstand einfach zu ungenaue Werte.

Das +/-5 hat nichts mit dem Zeichnen des Arcs zu tun. Es soll da nur ein kleiner Kreis gezeichnet werden, um die Endpukte des Bogens hervorzuheben.

Mario Peters
Beiträge: 9
Registriert: Sa 26. Apr 2025, 22:41

Re: TFPCustomCanvas Arc Methode, Verständnisfrage

Beitrag von Mario Peters »

Ich habe das Projekt gerade in der Bearbeitung, Ich versteh noch nicht warum der Winkel zwischen den Kreisen die die Bogenenden markieren, je nach Stellung der Scrollbars auch mal auf dem Bogen liegen, nicht an den Enden. Wenn ich den Scrollbar für StartAngle verändere liegen die kleinen Kreise auch mal außerhalb des Bogens. Ich nehme an, der rote Bereich markiert den eingeschlossenen Winkel. Der wird mit dem ScrollBar "Sweep Angle" verändert, der unterscheidet sich aber immer vom Winkel zwischen den beiden anderen Strecken ( Strahlen), die vom Ellipsenmittelpunkt aus über das Ellipsenrechteck (das die Ellipse umschließende Rechteck) hinaus gehen. Warum ist das so?
Du schreibst ja selber oben dass der Mittelpunkt der Ellppse mit den Punkten SX,SY, EX,EY verbunden wird, Dann werden die Schnittpunkte mit der Ellipse also intern berechnet. Soweit Ok, aber warum habe ich dann im Besidpileprojekt das hier oben in meiner Frage genannte Phänomen?

Antworten