złe wyświetlanie "kwadratowej spirali" zbudowanej z lini

0

Witam, jestem nowy na forum oraz nowy w w zabawie z C# :) otóż potrzebuję napisać kod na kwadratową spiralę, a właściwie przepisać na C# z Fortrana z książki "Wprowadzenie do grafiki komputerowej" Angella, ma ona wyglądać tak: user image

a u mnie wygląda tak: user image i nie wiem co jest nie tak, patrze i analizuję algorytm z książki i patrze na swój kod i nie mogę dojść do tego co mam źle. Prosiłbym o pomoc. Poniżej zamieszczam kod funkcji:

  
                int Y0 = Convert.ToInt32(pictureBox1.Height / 2);
                int X0 = Convert.ToInt32(pictureBox1.Width / 2);
                const int n = 4;
                int[,] P = new int[n, 2];
                int[,] PD = new int[n, 2];
                P[0, 0] = -200 + X0; P[0, 1] = 200 + Y0;
                P[1, 0] = 200 + X0; P[1, 1] = 200 + Y0;
                P[2, 0] = 200 + X0; P[2, 1] = -200 + Y0;
                P[3, 0] = -200 + X0; P[3, 1] = -200 + Y0;
                g.DrawLine(pen1, P[0, 0], P[0, 1], P[1, 0], P[1, 1]);
                g.DrawLine(pen1, P[1, 0], P[1, 1], P[2, 0], P[2, 1]);
                g.DrawLine(pen1, P[2, 0], P[2, 1], P[3, 0], P[3, 1]);
                g.DrawLine(pen1, P[3, 0], P[3, 1], P[0, 0], P[0, 1]);

                double SMU = 0.1;
                double RMU = 1 - SMU;
                for (int i = 0; i < 21; i++)
                {
                  
                    for (int j = 0; j < 4; j++)
                    {
                       
                        int NJ = j % 3 + 1;
                        
                        PD[j, 0] = Convert.ToInt32(RMU * P[j, 0] + SMU * P[NJ, 0]);
                        PD[j, 1] = Convert.ToInt32(RMU * P[j, 1] + SMU * P[NJ, 1]);
                         g.DrawLine(pen1, P[j, 0], P[j, 1], PD[j, 0], PD[j, 1]);
                        P[j, 0] = PD[j, 0];
                        P[j, 1] = PD[j, 1];
                       
                    }
                    for (int j = 0; j < 4; j++)
                    {
                      
                        g.DrawLine(pen1, P[0, 0], P[0, 1], P[1, 0], P[1, 1]);
                        g.DrawLine(pen1, P[1, 0], P[1, 1], P[2, 0], P[2, 1]);
                        g.DrawLine(pen1, P[2, 0], P[2, 1], P[3, 0], P[3, 1]);
                        g.DrawLine(pen1, P[3, 0], P[3, 1], P[0, 0], P[0, 1]);
                        
                    }

                  
                }

I tak wiem że trochę brzydki kod, ale to skromne początki :) Dziękuję za pomoc

1

Chciałbym pomóc, ale żeby to zrobić teraz trzeba by zgadywać mocno - nie wiemy z czego przepisujesz (ten kod w fortranie - nie każdy ma tą książkę w domu na półce, ja na pewno nie), można próbować się domyślić czemu ten kod nie działa ale to by było strzelanie w ciemno trochę.

Wrzuć chociaż zdjęcie z tą stroną książki (albo screen z pfc). Lepiej też by było mieć cały projekt (albo przynajmniej coś uruchamialnego), ale to niekonieczne.

0

tutaj proszę książka w pdf'ie: https://mhroczny.net/pub/sesja/grafika/Wprowadzenie_do_grafiki_komputerowej-Angell.pdf strona 26 /w pdf'ie 24/

a w załączniku folder z całym projektem, i kod ten znajduje się pod "radioButton10.checked" jeden z ostatnich if'ów

1

Nieaktualnie, poradziłem sobie sam stosując zamiast tablic listę punktów :)
Dzięki za zaangażowanie :)

0

ja w fortranie tez n ie pisze tylko w c# ;p a pseudokod/kod fortrana mam w książce którą polecono mi do podstaw grafiki komputerowej a dziękowałem za jakiekolwiek odzew bo takowy był :) a tutaj kod jakby ktoś był ciekaw :)

                int Y0 = Convert.ToInt32(pictureBox1.Height / 2);
                int X0 = Convert.ToInt32(pictureBox1.Width / 2);
                Point tmp = new Point(0, 0);
                Point pointC = new Point(X0 + 200, Y0 - 200);
                Point pointA = new Point(X0 + 200, Y0 + 200);
                Point pointB = new Point(X0 - 200, Y0 + 200);
                Point pointD = new Point(X0 - 200, Y0 - 200);
                List<Point> list = new List<Point>();
                pointA.X = X0 - 200;
                pointA.Y = Y0 + 200;
                pointB.X = X0 + 200;
                pointB.Y = Y0 + 200;
                list.Add(pointA);
                list.Add(pointB);
                list.Add(pointC);
                list.Add(pointD);
                int n = 21;    // liczba kwadratow
                double RMU = 0.9;
                for (int i = 0; i < (n * 4); i++)
                {
                    tmp.X = (int)(RMU * (list[i].X) + (1 - RMU) * list[i + 1].X);// 9/10 to mikro wspolczynnik podzialu odcinka
                    tmp.Y = (int)(RMU * (list[i].Y) + (1 - RMU) * list[i + 1].Y);
                    list.Add(tmp);
                }
                for (int i = 0; i < list.Count - 1; i++)
                {
                    g.DrawLine(pen1, list[i], list[i + 1]);

                }
                g.DrawLine(pen1, list[0], list[3]); 
0

Witam znów :)

nie zakładam po problem dotyczy tego samego projektu :)

planuję za pomocą "trackBar'a" mieć możliwość zmiany np długości promienia rysowanego okręgu tylko nie wiem jak tego dokonać aby na bieżąco aktualizowało mi picturebox'a o ile jest to możliwe :)

a jeżeli chodzi o program, to jest ten sam co poprzednio wrzuciłem z 2 małymi poprawkami: zamiast radiobutton'ów jest combobox i zamiast if'ów mamy switch'a :)

1

planuję za pomocą "trackBar'a" mieć możliwość zmiany np długości promienia rysowanego okręgu tylko nie wiem jak tego dokonać aby na bieżąco aktualizowało mi picturebox'a o ile jest to możliwe :)

Jasne że jest możliwe ;].

Jeśli rozumiem o co Ci chodzi, wystarczy podłączyć się pod ValueChanged:

(pisane z ręki i nietestowane, ale powinno działać)
Albo dodać w konstruktorze odręcznie:

trackBar1.ValueChanged += (sender, e) => {
    promienKola = trackBar1.Value;
    pictureBox1.Invalidate();
}

Albo w designerze kliknąć dwa razy na zdarzenie ValueChanged i w handlerze wkleić to Invalidate().

Ogólnie Invalidate() powoduje, można powiedzieć, 'usunięcie' wszystkiego narysowanego na pictureBox, i wywołanie jeszcze raz zdarzenia Paint (żeby narysować od nowa)

Przetestowałbym i wrzucił dokładne poprawki (bez zgadywania), ale na laptopie nie mam VS (bo i system nie windows).

0

ok, dzięki za odpowiedź, wrzuciłem jak pisałeś "pictureBox1.Invalidate();" do trackbara, ale zamiast aktualizować to po zmianie wartości parametru czyści ekran, a co do pierwszej opcji kompilator krzyczał o parametrach- sender i e.

o ile dobrze zrozumiałem i wszystko zrobiłem jak należy :)

1

ok, dzięki za odpowiedź, wrzuciłem jak pisałeś "pictureBox1.Invalidate();" do trackbara, ale zamiast aktualizować to po zmianie wartości parametru czyści ekran, a co do pierwszej opcji kompilator krzyczał o parametrach- sender i e.

O co chodzi z krzyczeniem o parametry nie wiem co końca. W każdym razie chodzi o dowolny handler zdarzenia.

Ad. czyszczenia ekranu - Invalidate() w zasadzie czyści kontrolkę, i na tym polega jej działanie. Następnie wywoływane jest zdarzenie Paint kontrolki, które powinno rysować wszystko od nowa.

Problem jest dlatego, że u Ciebie całe rysowanie odbywa się w button1.Click() przy użyciu obiektu stworzonego przy pomocy pictureBox1.CreateGraphics(). (niezbyt ładne rozwiązanie, ale skoro działa to nie będę narzekał). W takim razie musisz po prostu w obsłudze zdarzenia (wyczyścić kontrolkę i) jeszcze raz narysować to co chcesz (ze zmienionym promieniem). Kod odpowiedzialny za rysowanie już masz, musisz go tylko wywołać jakoś.

0

<quote="985452">

Problem jest dlatego, że u Ciebie całe rysowanie odbywa się w button1.Click() przy użyciu obiektu stworzonego przy pomocy pictureBox1.CreateGraphics().

wiem, że niezbyt ładne rozwiązanie lecz szczerze nie mam pomysłu jak to inaczej zrobić

a co do sender i e to zwraca coś takiego:

Error	1	A local variable named 'sender' cannot be declared in this scope because it would give a different meaning to 'sender', which is already used in a 'parent or current' scope to denote something else	

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