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.
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.
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 ;)
@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.