Prosty rysunek pokoju
Grafika,  Kodowanie

Prosty rysunek pokoju

Rysowanie uproszczonego planu pomieszczenia to w praktyce zadanie z pogranicza grafiki komputerowej, geometrii i reprezentacji danych. Nawet bardzo prosty model pokoju wymaga decyzji: jak zapisać ściany, jak odwzorować skalę, jak przechowywać obiekty oraz jak je narysować na ekranie lub w pliku. Te decyzje przekładają się później na poprawność obliczeń, możliwość modyfikacji oraz czytelność wizualną. W wielu zastosowaniach – od prostych aplikacji edukacyjnych po narzędzia do planowania wnętrz – wystarcza model dwuwymiarowy oparty o układ współrzędnych, w którym reprezentujemy ściany jako odcinki, a meble jako prostokąty, co dobrze oddaje ideę jaką niesie prosty rysunek pokoju.

Prosty rysunek pokoju jako reprezentacja geometryczna w układzie współrzędnych kartezjańskich i jego ograniczenia

Podstawą jest układ współrzędnych 2D. Przyjmujemy zwykle, że punkt (0,0) znajduje się w lewym dolnym rogu przestrzeni roboczej. Każdy element rysunku opisujemy współrzędnymi:

  • ściany → odcinki (x1, y1) → (x2, y2)
  • meble → prostokąty (x, y, szerokość, wysokość)
  • drzwi/okna → odcinki lub łuki

Ważna decyzja dotyczy jednostek. Jeśli 1 jednostka odpowiada 1 cm, uzyskujemy wysoką dokładność kosztem większych wartości liczbowych. Przy skali 1 jednostka = 10 cm zapis jest krótszy, ale tracimy szczegóły.

Przykład:

  • pokój 4 m × 5 m
  • zapis dokładny: 400 × 500
  • zapis uproszczony: 40 × 50

Ograniczenia modelu:

  • brak informacji o wysokości
  • brak perspektywy
  • brak fizycznych właściwości obiektów

Struktury danych opisujące ściany, meble i elementy wyposażenia w kontekście prostego modelu graficznego

Minimalny model danych można sprowadzić do kilku struktur.

ElementStrukturaOpis
Ściana(x1, y1, x2, y2)Odcinek
Mebel(x, y, w, h)Prostokąt
Drzwi(x, y, szerokość, kąt)Segment + rotacja

Przykłady implementacji:

JęzykKod
Pythonpython\nwalls = [(0,0,400,0), (400,0,400,300), (400,300,0,300), (0,300,0,0)]\nfurniture = [(50,50,100,50)]\n
Cc\nstruct Wall { int x1,y1,x2,y2; };\nstruct Rect { int x,y,w,h; };\n
C++cpp\nstruct Wall { int x1,y1,x2,y2; };\nstd::vector<Wall> walls;\n

Warto unikać przechowywania danych pochodnych, np. długości ściany, bo można ją zawsze obliczyć.

Prosty rysunek pokoju w kontekście algorytmu rysowania linii i prostokątów na ekranie lub w pliku graficznym

Rysowanie sprowadza się do rasteryzacji.

  • linie → algorytm Bresenhama
  • prostokąty → cztery linie lub wypełnienie

Algorytm Bresenhama działa w czasie liniowym względem długości odcinka i nie wymaga liczb zmiennoprzecinkowych.

JęzykKod
Cc\nvoid drawLine(int x1,int y1,int x2,int y2){\n int dx=abs(x2-x1), dy=abs(y2-y1);\n int sx = x1<x2?1:-1;\n int sy = y1<y2?1:-1;\n int err = dx-dy;\n while(1){\n putpixel(x1,y1);\n if(x1==x2 && y1==y2) break;\n int e2=2*err;\n if(e2>-dy){ err-=dy; x1+=sx; }\n if(e2<dx){ err+=dx; y1+=sy; }\n }\n}\n

| Python | python\ndef draw_rect(x,y,w,h):\n draw_line(x,y,x+w,y)\n draw_line(x+w,y,x+w,y+h)\n draw_line(x+w,y+h,x,y+h)\n draw_line(x,y+h,x,y)\n |

Złożoność:

  • linia: O(n)
  • prostokąt: O(4n)

Obsługa skali i transformacji współrzędnych przy przejściu z modelu logicznego do obrazu

Model logiczny nie jest bezpośrednio tym, co trafia na ekran.

Stosujemy trzy operacje:

  • skalowanie
  • przesunięcie
  • odwrócenie osi Y

Wzory:

OperacjaWzór
Skalowaniex’ = x * s
Przesunięciex’ = x + dx
Odwrócenie Yy’ = H – y

Przykład implementacji:

JęzykKod
Pythonpython\ndef transform(x,y,scale,dx,dy,H):\n x2 = x*scale + dx\n y2 = H - (y*scale + dy)\n return x2,y2\n

Typowy błąd: brak odwrócenia osi Y, przez co rysunek jest odwrócony.

Wykrywanie kolizji i poprawność geometryczna przy rozmieszczaniu obiektów w pokoju

Kolizje wykrywamy dla prostokątów osiowo wyrównanych.

x1<x2+w2x1+w1>x2y1<y2+h2y1+h1>y2x_1 < x_2 + w_2 \land x_1 + w_1 > x_2 \land y_1 < y_2 + h_2 \land y_1 + h_1 > y_2x1​<x2​+w2​∧x1​+w1​>x2​∧y1​<y2​+h2​∧y1​+h1​>y2​

Warunek oznacza, że dwa prostokąty nachodzą na siebie.

Implementacja:

JęzykKod
C++cpp\nbool collide(Rect a, Rect b){\n return (a.x < b.x+b.w && a.x+a.w > b.x &&\n a.y < b.y+b.h && a.y+a.h > b.y);\n}\n

Złożoność:

  • naiwnie: O(n²)
  • optymalnie: użycie podziału przestrzeni

Prosty rysunek pokoju jako baza do dalszego rozwoju: eksport do SVG, JSON i wizualizacja w przeglądarce

Format SVG pozwala na zapis wektorowy.

FormatKod
SVGxml\n<svg width=\"500\" height=\"400\">\n <rect x=\"50\" y=\"50\" width=\"100\" height=\"50\" fill=\"gray\"/>\n <line x1=\"0\" y1=\"0\" x2=\"400\" y2=\"0\" stroke=\"black\"/>\n</svg>\n

Format JSON:

FormatKod
JSONjson\n{\n \"walls\": [[0,0,400,0]],\n \"furniture\": [[50,50,100,50]]\n}\n

Zastosowania:

  • zapis projektu
  • komunikacja między modułami
  • wizualizacja w przeglądarce

Uwagi praktyczne wynikające z implementacji i błędów spotykanych w prostych projektach graficznych

Niespójna skala prowadzi do błędów trudnych do wykrycia.
Brak zamknięcia ścian powoduje nieszczelny model.
Zaokrąglenia zmiennoprzecinkowe wprowadzają przesunięcia pikselowe.
Zbyt duża liczba obiektów bez optymalizacji spowalnia rysowanie.
Nieprawidłowa kolejność rysowania powoduje zasłanianie elementów.

FAQ

Czy trzeba używać algorytmu Bresenhama?
Nie, ale jest wydajny i prosty.

Czy model 2D wystarcza?
Tak do planowania, nie do wizualizacji 3D.

Jak dobrać skalę?
Najczęściej 1 jednostka = 1 cm lub 10 cm.

Czy SVG jest lepsze od bitmapy?
Tak przy skalowaniu i edycji.

Jak wykrywać kolizje?
Test AABB.

Czy Python nadaje się do takich projektów?
Tak, szczególnie do prototypów.

Czy trzeba używać bibliotek graficznych?
Nie, ale upraszczają pracę.

Źródło Foto: Freepik

Dodaj komentarz