
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.
Spis Treści
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.
| Element | Struktura | Opis |
|---|---|---|
| Ś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ęzyk | Kod |
|---|---|
| Python | python\nwalls = [(0,0,400,0), (400,0,400,300), (400,300,0,300), (0,300,0,0)]\nfurniture = [(50,50,100,50)]\n |
| C | c\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ęzyk | Kod |
|---|---|
| C | c\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:
| Operacja | Wzór |
|---|---|
| Skalowanie | x’ = x * s |
| Przesunięcie | x’ = x + dx |
| Odwrócenie Y | y’ = H – y |
Przykład implementacji:
| Język | Kod |
|---|---|
| Python | python\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+w2∧x1+w1>x2∧y1<y2+h2∧y1+h1>y2
Warunek oznacza, że dwa prostokąty nachodzą na siebie.
Implementacja:
| Język | Kod |
|---|---|
| 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.
| Format | Kod |
|---|---|
| SVG | xml\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:
| Format | Kod |
|---|---|
| JSON | json\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


