Sześciany obracane trzema suwakami wokół trzech osi

0

Witam. Na zaliczenie przedmiotu dostałem projekt programu, który ma generować sześcian obracany 3 suwakami wokół 3 osi. Niestety problem ten mnie przerósł. Prowadzący nakierował mnie w ten sposób, że mam zrobić na poczatku klasy : punkty, krawedz, sciana, szescian. Gdzie pierwsza klasa ma przechowywać współrzędne punktów x,y,z. Druga ma przechowywać informacje o krawędzi, która składa się z 2 punktów itd. Później w klasie sześcian wszystko ma być łączone i rysowane. Na razie w ogóle nie myślę o obrocie wokół osi, a o samym zaprojektowaniu sześcianu. Wszystkie dane mają być wprowadzane z poziomu Editów w programie. I tu już zaczął się mój pierwszy problem, gdyż nie wiem jak zapisać żeby do klasy Tpunkt przechowującej x,y,z wprowadzać dane z 3 editów tak żeby każdy pierwszy zapisywał współrzędne do X, drugi do Y, a trzeci do Z i byłoby to zapisane jako jeden rekord w tablicy. Bardzo bym prosił o pomoc z moim programem. Za każdą pomoc i podpowiedzi będę niezmiernie wdzięczny. Pozdrawiam.

0

Ogólna struktura klasy sześcianu mogłaby wyglądać tak jak poniżej:

type
  { wierzchołek krawędzi }
  TCube3DVertex = record
    X, Y, Z: Double;
  end;

type
  TCube3DVertexKind  = (cvkFirst, cvkSecond);
  TCube3DVertexesArr = array [TCube3DVertexKind] of TCube3DVertex;

type
  { krawędź ściany }
  TCubeEdge = class(TObject)
  private
    FVertexes: TCube3DVertexesArr;
  private
    function GetVertex(AKind: TCube3DVertexKind): TCube3DVertex;
    procedure SetVertex(AKind: TCube3DVertexKind; AVertex: TCube3DVertex);
  public
    constructor Create();
  public
    property First: TCube3DVertex index cvkFirst read GetVertex write SetVertex;
    property Second: TCube3DVertex index cvkSecond read GetVertex write SetVertex;
  end;

type
  TCubeEdgeKind = (cekLeft, cekTop, cekRight, cekBottom);
  TCubeEdgesArr = array [TCubeEdgeKind] of TCube3DVertex;

type
  { ściana sześcianu }
  TCubeSide = class(TObject)
  private
    FEdges: TCubeEdgesArr;
  private
    function GetEdge(AKind: TCubeEdgeKind): TCubeEdge;
    procedure SetEdge(AKind: TCubeEdgeKind; AEdge: TCubeEdge);
  public
    constructor Create();
    destructor Destroy(); override;
  public
    property Left: TCubeEdge index cekLeft read GetEdge write SetEdge;
    property Top: TCubeEdge index cekTop read GetEdge write SetEdge;
    property Right: TCubeEdge index cekRight read read GetEdge write SetEdge;
    property Bottom: TCubeEdge index cekBottom read GetEdge write SetEdge;
  end;

type
  TCubeSideKind = (cskLeft, cskTop, cskRight, cskBottom, cskFront, cskBack);
  TCubeSidesArr = array [TCubeSideKind] of TCubeSide;

type
  { sześcian }
  TCube = class(TObject)
  private
    FSides: TCubeSidesArr;
  private
    function GetSide(AKind: TCubeSideKind): TCubeSide;
    procedure SetSide(AKind: TCubeSideKind; ASide: TCubeSide);
  public
    constructor Create();
    destructor Destroy(); override;
  public
    property Left: TCubeSide index cskLeft read GetSide write SetSide;
    property Top: TCubeSide index cskTop read GetSide write SetSide;
    property Right: TCubeSide index cskRight read GetSide write SetSide;
    property Bottom: TCubeSide index cskBottom read GetSide write SetSide;
    property Front: TCubeSide index cskFront read GetSide write SetSide;
    property Back: TCubeSide index cskBack read GetSide write SetSide;
  end;

Metody trzeba uzupełnić i dodać np. taką, która na podstawie współrzędnych któregoś wierzchołka i szerokości ściany sześcianu uzupełni wszystkie pod-obiekty (zainicjuje wartości ich pól); To tak na szybko pisane - być może inna struktura będzie lepsza;

Samo wpisanie danych (współrzędnych) do podobiektów to nic innego jak konwersja łańcuchów z pól edycyjnych i wpisanie wyników konwersji poprzez odpowiednie właściwości klas (ewentualnie metody, ale to już pozostawiam Tobie);

Ale jak to pieroństwo obracać według wszystkich trzech osi i rysować na ekranie to już nie mnie pytaj - nie znam się na tym kompletnie; Jakieś wzory do tego istnieją, ale nie bawiłem się jeszcze grafiką trójwymiarową, więc zbyt wiele nie wiem.

0

Bardzo dziękuje za pomoc. Baaardzo mi to pomogło. Myślę, że z rysowaniem z małą pomocą znajomego jakoś sobie poradzimy, jednak co do tego nieszczęsnego obrotu to będę musiał porozmawiać z prowadzącym. Na pewno podziele się jego pomysłem, może w przyszłości komuś też się to przyda ;)

0

@czery - lepiej by było gdybyś nie robił tego w taki sposób, w jaki sugeruje prowadzący; O ile moja propozycja realizuje propozycję prowadzącego, to będzie trzeba nastukać trochę więcej kodu;

Jeśliby skorzystać z propozycji @bogdansa - kod uprościłby się do poniższej postaci:

type
  TCube3DVertex = record
    X, Y, Z: Double;
  end;

type
  TCube3DVertexKind  = (cvkHorizontal, cvkVertical, cvkDeep);
  TCube3DVertexesArr = array [TCube3DVertexKind] of TCube3DVertex;

type
  TCube = class(TObject)
  private
    FVertexes: TCube3DVertexesArr;
  private
    function GetVertex(AKind: TCube3DVertexKind): TCube3DVertex;
  public
    constructor Create();
  public
    property Horizontal: TCube3DVertex index cvkHorizontal read GetVertex;
    property Vertical: TCube3DVertex index cvkVertical read GetVertex;
    property Deep: TCube3DVertex index cvkDeep read GetVertex;
  end;

Do tego należy dodać metodę pobierającą współrzędne co najmniej jednego wierzchołka (jeśli początkowa pozycja sześcianu ma być z góry określona) i np. szerokości ściany sześcianu oraz dodać metody, umożliwiające obrót bryły według zadanych osi; Do konwersji gołych liczbowych współrzędnych przyda się funkcja/metoda zwracająca wypełnioną strukturę, np.:

function Cube3DVertex(AX, AY, AZ: Double): TCube3DVertex;
begin
  Result.X := AX;
  Result.Y := AY;
  Result.Z := AZ;
end;

Pozostanie Ci tylko obliczanie współrzędnych wierzchołków, aby móc wyświetlić sześcian na ekranie.

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