Rysowanie gwiazdy pustej w środku

0

Witam!

Od kilku dni staram się narysować na Canvasie gwiazdę pięcioramienną, która będzie pusta w środku.
Znalazłem podobne tematy:

ale w żadnym z nich nie ma takiego kodu, żeby narysował właśnie taką gwiazdę jaką chcę, a jeśli
już to musi mieć ona duże rozmiary, a potrzebuje małej. Sam doszedłem do narysowania pentagramu.

Efekt, który uzyskałem wygląda mniej więcej tak:

http://pl.wikipedia.org/w/index.php?title=Plik:Pentagram_green.svg&filetimestamp=20070309050356

Dążę do narysowania takiej gwiazdy:

http://pl.wikipedia.org/w/index.php?title=Plik:Five-pointed_star.svg&filetimestamp=20091210212909

  procedure Star(Left, Top: Integer; N, R: Byte);
  var
    i, x, y: Integer;
  begin
    if N < 5 then
      Exit;

    with Image1.Canvas do
     begin
       MoveTo(Left, Top);
       for i := 1 to (N * 2) do
        begin
          y := Round(Sin(DegToRad(180 * ((N - 1) / N)) * i) * R);
          x := Round(Cos(DegToRad(180 * ((N - 1) / N)) * i) * R);
          Left := Left + x;
          Top := Top + y;
          LineTo(Left, Top);
        end;
     end;
  end;

Proszę o jakąkolwiek pomoc!

Pozdrawiam

0

Dam ci taką radę: jeżeli nie potrafisz zrobić czegoś tak od razu, to spróbuj podzielić problem na mniejsze problemy, z którymi sobie radzisz. Rozwiąż je przy pomocy osobnych funkcji. Przykład: Zauważ, że ta gwiazda ma 5 identycznych ramion. różnica polega tylko na tym, że są obrócone o pewien kąt i znajdują się w innej pozycji. Napisz funkcję, która rysuje ramię w wybranej pozycji i o wybranym kącie. Potem wywołaj tę funkcję 5 razy z odpowiednimi parametrami.

1

Właściwie to było bardzo ciekawe zadanie nie z punktu widzenia programowania zaś z punktu widzenia matematyki.
Bez matematycznego rozwiązania nie da rady tego zadania rozwiązać (wg mnie, poprawcie jeżeli się mylę).

procedure TForm1.Star(Left,Top,N:Integer;R:Double);
var I,D:Integer;
var S:Double;
begin
  if N>2 then
  begin
    D:=(N-1)shr(1);
    S:=R*abs(Cos(D*Pi/N)/Cos((Pi-D*Pi)/N));
    Image1.Canvas.MoveTo(Left+Round(S*Sin(-Pi/N)),Top-Round(S*Cos(-Pi/N)));
    for I:=0 to N-1 do
    begin
      Image1.Canvas.LineTo(Left+Round(R*Sin(2*i*Pi/N)),Top-Round(R*Cos(2*i*Pi/N)));
      Image1.Canvas.LineTo(Left+Round(S*Sin((2*i+1)*Pi/N)),Top-Round(S*Cos((2*i+1)*Pi/N)));
    end;
  end;
end;
1

_13th_Dragon, mnie też zaciekawiło to zadanie z matematycznego punktu widzenia. Zresztą sama gwiazda pitagorejska (lub inaczej pentagram) już sama w sobie jest ciekawa, choćby ze względu na ukryty w niej złoty podział.
Aby narysować pentagram bez wewnętrznych linii trzeba znaleźć współrzędne punktów przecięcia poszczególnych ramion. Przyjmując, że zewn. wierzchołki po połączeniu tworzą pięciokąt foremny wpisany w okrąg o promieniu R, wówczas wierzchołki wewn. tworzą pięciokąt wpisany w okrąg o promieniu r i obrócony o kąt 36 stopni. Oczywiście obydwa okręgi mają wspólny środek

Wykorzystując złoty podział wyszło mi, że ten promień wynosi r = 0,5 (3 - sqrt(5)) R

Mając dane obydwa promienie dalej już jest z górki, wystarczy wykorzystać równanie parametryczne okręgu:

procedure Pentagram(Promien, X, Y, Kat: Integer; Kanwa: TCanvas);
var i, R1, R2: Integer;
begin
  R1:= Promien;
  R2:= Round(R1*(3-Sqrt(5))/2);  // R2 może być typu rzeczywistego, aby 2 razy nie zaokrąglać
  Kanwa.MoveTo(X + Round(Cos((Kat+54)*Pi/180)*R1), Y + Round(Sin((Kat+54)*Pi/180)*R1));
  for i:= 1 to 5 do begin
    Kanwa.LineTo(Round(X + Cos((i*72+18+Kat)*Pi/180)*R2), Y + Round(Sin((i*72+18+Kat)*Pi/180)*R2));
    Kanwa.LineTo(Round(X + Cos((i*72+54+Kat)*Pi/180)*R1), Y + Round(Sin((i*72+54+Kat)*Pi/180)*R1));
  end;
end;

Poszczególne dane oznaczają
Promień - dotyczy większego okręgu (mieści się w nim pentagram)
X i Y - współrzędne środka okręgów
Kąt - kąt obrotu pentagramu w stopniach od 0 do 71 (dalej będzie się powtarzać co 72 stopnie)
Kanwa - gdzie narysować

0

Wzór ogólniejszy (n nieparzyste, łączymy co drugi wierzchołek) na promień wewnętrznego okręgu jest taki: r = R cos(2π/n)/cos(&pi/n). Prosta trygonometria.

0

Wyznacz w punkcie A srodek gwiazdy. Potem użyj wzoru:

var Tablica : array [1..5] of TPoint;
begin
  for I := 1 to 5 do
    begin
      Tablica[I].X := A.X + Odl * Sin(Angle /180 * Pi);
      Tablica[I].Y := A.Y + Odl * Cos(Angle /180 * Pi);
      Angle := Angle + 72;
    end;
end;

Gdzie Odl to Odleglosc czyli "promień" gwiazdy, Angle to kat ktory zwiększaj o 72 (365:5), Pi ~3,1415.
Potem mając wspolrzedne tych pieciu ramion gwiazdy użyj funkcji:

Canvas.MoveTo();
Canvas.LineTo();

Edit: A, ważna sprawa, to ma byc ten po lewej czy prawej?
user image

2

@TomRiddle, proponuję byś wykonał taki kod:

boolean nieRozumiemPytania=true;
while(nieRozumiemPytania)
{
   czytamPytanie);
   nieRozumiemPytania=!zrozumialemPytanie();
   
}
odpowiadam();
0

Weisstein, Eric W. "Pentagram." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/Pentagram.html
user image

0

Dziękuję wszystkim za zainteresowanie się tym tematem.
_13th_Dragon i simplex, Wasz kod świetnie rysuję gwiazdę nie zależnie od rozmiarów promienia,
za co bardzo Wam dziękuję :)

0

Weisstein, Eric W. "Star Polygon." From MathWorld--A Wolfram Web Resource.
http://mathworld.wolfram.com/StarPolygon.html

0

Ogólny wzór (n, k nie muszą być względnie pierwsze) jest taki: r = Rsin(β)/sin(π-β-α/2), α = 2π/n, β=(1/2)(π-kα) .
Na zewnętrznym okręgu są wierzchołki (Rcos(&alphai),Rsin(&alphai)), na wewnętrznym (rcos(&alphai+α/2),rsin(&alphai+α/2)) i=0,...,n-1.
Przydała się szkolna trygonometria.
user image

1 użytkowników online, w tym zalogowanych: 0, gości: 1