Narzędzie do rysowania linii i bounding box

Narzędzie do rysowania linii i bounding box
tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 597
0

Cześć.
Muszę podjąć ważną decyzję architektoniczną i nie mogę się zdecydować.

Otóż piszę narzędzie do tworzenia linii w programie do edycji grafiki.

Narzędzie linia dziedziczy po ResizableTool.
Narzędzie ResizableTool ma punkty graniczne i rect jak na załączonej grafice.
Moje pytanie brzmi. Czy dla narzędzia linii również generować taki rect czy nie?
Ten bounding box byłby przydatny do wizualizacji obszaru, który można skopiować lub wyciąć.

Nie mogę się zdecydować. Liczę na Waszą pomoc :-)

Poglądowa grafika bounding box:
pogląd

obscurity
  • Rejestracja: dni
  • Ostatnio: dni
1

To nie jest decyzja architektoniczna ani nawet ważna tylko mały detal w UX.
Niektórym się będzie podobać to, innym to; żeby uszczęśliwić wszystkich ja wyznaję w większości sytuacji prostą zasadę - jeśli nie możesz się zdecydować bo wszystkie rozwiązania wydają się równie dobre to zrób to konfigurowalne i pozwól zdecydować użytkownikowi.

tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 597
0

Zrobię tak:
-tworzenie linii - poprzez LPM z punktu startowego do kursora
-linia gotowa - z dwoma punktami na krańcach bez bounding box
-kopiowanie linii - konwersja na zwykły obraz czyli będzie bounding box po wklejeniu

SL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1134
1

Narzędzie linia dziedziczy po ResizableTool.

Poczytaj o kompozycji vs dziedziczenie. Hierarchie dziedziczenia zazwyczaj nie działają w skomplikowanych przypadkach a zwłaszcza w grach, gdzie jest to dużo bardziej skomplikowane niż typowy CRUD https://gamedev.stackexchange.com/questions/22483/should-i-use-inheritance-or-composition-for-modelling-game-objects

LukeJL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8536
0

Warto oddzielić to, co jest na ekranie, GUI (czyli ten bounding box) od samej logiki danego narzędzia do rysowania linii.
No bo takie narzędzie do generowania linii może być bardzo proste:

  1. przyjmij pozycję x,y i zapamiętaj ją jako punkt startowy
  2. w pętli: nasłuchuj pozycji x,y i emituj ją jako punkt końcowy (z możliwością update'u)
  3. poczekaj na zatwierdzenie pozycji x,y i emituj ją jako punkt końcowy

czyli w pseudokodzie:

Kopiuj
start = null
end = null

event = await mouseDown
start = event.position
while event = await mouseUp or mouseMove:
    end = event.position
    match event:
         mouseMove:
             emit {start, end, done=false}
         mouseUp:
             emit {start, end, done=true}
             return


Natomiast to nie ma wiele wspólnego z tym czy coś jest resizable. Równie dobrze takie narzędzie może działać headless. Np. mógłbyś mieć system wtyczek i odpalać narzędzie z poziomu wtyczki.

Czyli ja bym trzymał oddzielnie ResizableTool (jako coś, co odpowiada za bounding boxy) od samego narzędzia rozumianego jako logiczny sposób interakcji/generowania konkretnej geometrii.

Wtedy też decyzja jak to będzie w GUI nie będzie żadną ważną decyzję architektoniczną, a po prostu tym, czy podepniesz ResizableTool pod logikę narzędzia, czy nie podepniesz. Opieranie się na dziedziczeniu w tym momencie wydaje się hakiem implementacyjnym, a nie czymś, co ma sens na poziomie architektury.

JU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5052
0

W Cadach (Autocad, Intellicad, Gstarcad itd) jest to rozwiązane bardzo prosto.
Masz obiekt, np. linia, czy kółko. Każdy z tych rysowanych obiektów należy do bazy danych i dziedziczy po czymś tam wspólnym. Każdy z tych obiektów (na poziomie klasy abstrakcyjnej) ma metody w stylu draw, save i calculateBoundingBox (oczywiście jest też mnóstwo innych).

Czy to jest niezgodne z zasadą SRP? Tak. Ale tak to zostało napisane i działa już kilkadziesiąt lat :) No i przez to, że Autocad tak działa, wszystkie jego klony również (głównie te oparte na silniku ODA).

Oczywiście nikt Ci nie broni wydzielić odpowiedniej logiki rysowania, czy liczenia bounding boxów do osobnych klas i używania tego w głównym obiekcie. Ja bym pewnie tak zrobił. Coś w stylu:

Line
LineDrawer
LineGeometryCalculator. I oczywiście Line wykorzystuje te inne klasy.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.