Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: raczej matematyka niz php
Forum PHP.pl > Forum > PHP
hao
Sprawa oczywiście dotyczy progamowania w php, ale problem jest typowo matematyczny, niemniej jednak, może ktoś kto dobrze zna macierze pomoże mi... offtopic.gif

Otóż, proszę sobie wyobrazić pole 100x100 kwadratów/pixeli/dowolnych obiektów.
Nastepnie gdzieś na tym polu znajduje się "oko" - punkt A(x, y).
Dla przykładu niech Ax=40, Ay=60.
"Oko" obserwuje wszystko naokoło.
Zacznijmy od punktu (0, 0). "Oko patrzy" na ten punkt po jakiejś lini.
Chciałbym móc określić współrzędne tej lini od punktu (Ax, Ay) do (0, 0) w tablicę.
Następnie oko przekręca się w prawo i patrzy na punkt (1, 0)... następnie (n, 0), (100, 0). "Oko" patrzy po obwodzie okręgu oczywiście, więc następnym punktem będzie (100, 1), potem (100, 2) itd.

Chciałbym dla każdej lini/promienia zbudować mniej więcej taką tablicę:

$promien[n]="x,y";

gdzie n to długość promienia.

Mam nadzieję, że nikogo nie razi pseudo kod, ale uczono mnie, że to pomoga jaśniej wyjaśnić o co chodzi :]
Docelowo ująłbym to taki w pseudokod:

  1. <?php
  2. FOR (Bx=0 By=0, wykonuj pętlę aż zakreślisz pełny obwód koła po którym patrzy 'oko', Bx++ By++) //zwraca współrzędne Bx i By*
  3. {
  4. $r=promień (tak naprawdę to długość wektora (Ax Ay) -> (Bx By))
  5.  
  6. FOR ( $i=0; $i<=$r; $i++) //po kolei każda kolejna jednostka długości promienia
  7. {
  8.  $wspolrzedne_r[$i]=(Rx, Ry) // Jak je określić?
  9. }
  10. }
  11. ?>


* Nie mam pomysłu jak określić pętlę, która będzie zataczać taki okrąg w układzie kartezjańskim (a tak naprawdę kwadrat, jeśli można tak napisać). Ewentualnie mógłbym zrobić 4 pętle dla każego boku kwadratu.

Największy problem stanowi dla mnie określenie kolejnych współrzędnych poszczególnych odcinków promienia/wektora.

Wynikiem tego w każdej pętli będzie taka tablica:

$wspolrzedne_r[]=array("x1,y1", "x2,y2", "x3,y3", "xn, yn");

Oczywiście współrzędne xn=Bx i yn=By.
Vengeance
hmm wiec tak... nie wiem czy oto ci chodziło ale:



Czyli |AB| to będzie długość promienia...

  1. <?php
  2. // nasz prostakat
  3. $rect['width'] = 100;
  4. $rect['height'] = 50;
  5.  
  6. // nasze 'oko'
  7. $eye = array('x' => 50, 'y' => 50);
  8.  
  9. // obliczamy dla kazdego punktu odleglosc od oka
  10. for($y=0; $y<$rect['height']; $y++)
  11. {
  12.  for($x=0; $x<$rect['width']; $x++)
  13.  {
  14. $r = sqrt( pow($eye['x']-$x, 2) + pow($eye['y']-$y, 2) );
  15. $result[$r] = array('x' => $x, 'y' => $y);
  16.  }
  17. }
  18. ?>


Sadze ze powinno dzialac ale gdzies moga byc male bledy smile.gif
hao
Dzięki, przyda się, jednak jak określić współrzędne żółtych pól, począwszy od 'oka' do celu (umiszczając je w tablicy oczywiście PO KOLEI)
Vengeance
Hmm smile.gif
Tego to już nie wiem :/

Jedyny, pewnie idiotyczny pomysł jaki mi przychodzi teraz do głowy to:
1. ponieważ wektor AB "przemieszcza" się po osi OY od pól 0 do 8 można,
2. kolejno mnożyć wektor przez skalar: 1/9 ; 2/9 ; 3/9 ; 4/9 itd...
3. mając teraz współrzędne punktu A oraz nowo powstałego wektora AX, obliczamy współrzędne punktu X

Hmmm... chyba jednak to nie ma sensu ;]
Kuziu
Jak pewnie zauważyłeś ... linia ma Height 9 pól natomiast Width 3 pola

Gdy teraz podzielisz 9/3 ... to wiesz co ile pól linia skręca ... problem pojawi się przy 10/3 ... będziesz musiał wybrać losowo lub jakoś inaczej miejsce skętu 1 z pól...
hao
Wiecie co, nawet mi pomogliście. Z tym mnożeniem wektorów.
Vengeance podsunął mi pomysł, a Kuziu podpowiedział jak go dopracować.

Otóż to dzielenie wysokości przez szerokość (np 10/3) bardzo dobrze się sprawdzi, jeśli tylko prowadzimy dodatkową zmienną $reszta, do której będziemy kolejno dodawać resztę z dzielenia. Kiedy $reszta>=1: "skręt lini" będzie o 1 pole dłuższy i $reszta--1; Dodatkowo jeśli kończy się wektor a została jakaś reszta to $reszta=1;
Czyli wys10 szer3 to będą takie elementy: 3, 3, 4.
wys20 szer3 to: 3, 3, 3, 4, 3, 3, 1

Jest to wg. mnie całkiem zadowalające. Dzięki za nakierowanie mnie na własciwy tor smile.gif guitar.gif
Vengeance
Ok nie ma sprawy smile.gif W sumie fajny wątek z tego wyszedł smile.gif

Rzuć jeszcze może swoim kodem co? ;] Może przyda się na przyszłość.
Zresztą chce zobaczyć jak połączyłeś te nasze "sposoby" bo z opisu to długo by rozkminiać snitch.gif
hao
Kod oczywiście skróciłem, żeby pokazać tylko to co wazne (faktyczny wynik TEGO kodu będzie trochę nieścisły, ponieważ nalezy uwzględnić jeszcze ćwiartki na układzie kartezjańskim i w zalezności od tego pomnożyć zmianną $new_a i $new_b przez -1 albo 1). I pominąłem te zliczanie modulo, poniważ okazało się zbędne.

Aha. jeszcze jedna uwaga, ćwiartki nie są tutaj takie jak uczono w szkole :]. Są takie jakby przekręcić układ kartezjański o 45 stopni. Dzięki temu w 1 ćwiartce zawiera się cały bok prostokąta(planszy), gdzie x=max, y=0->max. Ćw. 2 - x=0->max, y=max, Ćw. 3 - x=0, y=0->max. Ćw. 4 - x=0->max, y=0.

I oczywiście układ współrzędnych taki jak w php a nie klasyczny :-)

  1. <?
  2. $n=0; //zmienna pomocnicza (to na później)
  3.  
  4. $x=2; // \"oko\"
  5. $y=5;
  6.  
  7. $kloc[$i][$j] //tablica 39x39 zawirająca \"planszę\".
  8.  
  9. $xb=39; // punkty docelowe (gdzie oko patrzy)
  10. $yb=3;
  11.  
  12. // Tw. Pitagorasa oraz trygonometria, jak obliczyć boki trójkąta powstałego;
  13. /*
  14.                                                                           ......
  15. .......
  16.                                                                 ..........      
  17.        |
  18.                                           dl_ c      ...........                
  19.      |
  20.                                            ...........                          
  21.        |
  22.                                    ..........                                   
  23.        | dl_a
  24.                        ............                                             
  25.        |
  26.                ..........                                                       
  27.        |
  28.         ......       a   )                                                              |
  29.   ----------------------------------------------------------------------
  30.                                               dl_b
  31. */ 
  32.  
  33. $dl_c=(sqrt(pow($x-$xb, 2) + pow($y-$yb, 2))); //tw. pitagorasa BOK c
  34.  
  35. $dl_b=39-$x;  // szerokość planszy - pozycja_x \"oka\" BOK b
  36.  
  37. $cosa=cos($dl_b/$dl_c); // z tw. trygonometrycznego ... sinus a
  38.  
  39. $dl_a=(sqrt(pow($dl_c, 2) - pow($dl_b, 2))); // tw. pitagorasa. BOK a
  40.  
  41. $sina=sin($dl_a/$dl_c); // cosinus a
  42.  
  43. // teraz mamy odcinek c, czyli drogę, po której oko patrzy. Należy znaleść punkty 
  44. a układzie dla każdego kolejnego odcinka boku c, czyli po kolei new_c=1, new_c=2
  45.  new_c=3 itd. Zwróć uwagę, że każdy z fragmentów new_c jest pod takim samym kąte
  46.  jak c względem osi x.
  47.  
  48. $new_b=0;
  49. $n=0;
  50. while($new_b<$dl_c) // dlaczego akurat $new_b<$dl_c? Bo odcinek new_b mówi nam dokąd na osi x będzie ciągnięta linia wzroku.
  51.  {
  52. $new_b=round($cosa*$n);  // $n to jest kawałeczek przeciwprostokątnej $dl_c
  53. $new_a=round($sina*$new_b)*-1; //tutaj ponożyłem przezz '-1' poniważ w moim przykładzie znajdujemy się w 1 ćwiartce, a $y>$yb;
  54. $kloc[$new_a+$y][$new_b+$x]=&#092;"3\"; //zmieniamy element planszy na cyfrę symbolizującą np. czarny punkt.
  55. $n++;
  56.  }
  57.  
  58. // potem zostało nam tylko rysowanie:
  59.  
  60. for ($i = 0; $i<=$wys; $i++)
  61.  {
  62.  
  63. for ($j = 0; $j<=$szer; $j++)
  64.     {
  65.  
  66.     if(($i==$y)&&($j==$x)): print(&#092;"<img src=\"oczko.gif\">\");
  67.     elseif(($i==$yb)&&($j==$xb)): print(&#092;"<img src=\"oczko.gif\">\");
  68.     else:
  69.         {
  70.         if($kloc[$i][$j]==&#092;"1\"): print(\"<img src=\"trawka.gif\">\");
  71.         elseif($kloc[$i][$j]==&#092;"9\"): print(\"<img src=\"przeszkoda.gif\">\"); 
  72.         elseif($kloc[$i][$j]==&#092;"3\"): print(\"<img src=\"wzrok.gif\">\"); 
  73.         endif;
  74.         }
  75.     endif;
  76.     }
  77.  }
  78. ?>




Edit: Druga wersja: Oczko patrzy sobie dookoła, a "budynki" zasłaniają widok: tutaj OKO wyknonuje pełny obrót (no dokładniej to od $a do 360 st). Zasięg wzroku to zmiena $r. Ten skrypt wykorzystałem ostatecznie.

  1. <?
  2.  
  3. $x=15; // położenie oka
  4. $y=15;
  5.  
  6. $n=0; // zmienna, która bedzie przechowywać kolejne odcinki promienia 
  7. $a=0; // kąt alfa
  8.  
  9. $kloc[$i][$j]=.... //tablica 39x39, gdzie 0=cień, 1=trawa, 2= budynek
  10.  
  11. $r=40; // promien
  12. $new_x=0;
  13.  
  14. for ($kat = 0; $kat<360; $kat++)
  15. {
  16.  
  17. $cien=0;
  18.  
  19. for ($n = 0; $n<$r; $n++)
  20.  {
  21. $cosa=cos(deg2rad($kat));
  22. $sina=sin(deg2rad($kat));
  23. $new_x=($cosa*$n);  // new_x i new_y to współrzędne jest kawałeczka r o długości $n
  24. $new_y=($sina*$n);
  25.  
  26. if($cien==1): $kloc[$new_y+$y][$new_x+$x]=&#092;"3\";
  27. elseif(($kloc[$new_y+$y][$new_x+$x]==&#092;"9\")&&($cien==0)): $cien=1;
  28. else: $kloc[$new_y+$y][$new_x+$x]==&#092;"3\";
  29. endif;
  30.  }
  31. }
  32.  
  33. for ($i = 0; $i<=$wys; $i++)
  34.  {
  35. for ($j = 0; $j<=$szer; $j++)
  36.     {
  37.  
  38.     if(($i==$y)&&($j==$x)): print(&#092;"<img src=\"oczko.gif\" alt=\"$i:$j\">\");
  39.     else:
  40.         {
  41.         if($kloc[$i][$j]==&#092;"1\"): print(\"<img src=\"1.gif\" alt=\"$i:$j\">\"); //trawka
  42.         elseif($kloc[$i][$j]==&#092;"9\"): print(\"<img src=\"2.gif\">\"); //przeszkoda 
  43.         elseif($kloc[$i][$j]==&#092;"3\"): print(\"<img src=\"0.gif\">\"); //cien
  44.         endif;
  45.         }
  46.     endif;
  47.     }
  48.  print(&#092;"<br>\");
  49.  }
  50. ?>
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.