p align="left">Нужно отсортировать вершины так, чтобы вершина A была верхней, C - нижней, тогда min_y = A.y, max_y = C.y, и надо обойти все линии от min_y до max_y. Рассмотрим какую-то линию sy, A.y <= sy <= C.y. Если sy < B.y, то она пересекает стороны AB и AC; если sy >= B.y - то стороны BC и AC. Известны координаты всех вершин, поэтому можно написать уравнения сторон и найти пересечение нужной стороны с прямой y = sy. Получим два конца отрезка. Так как не известно, какой из них левый, а какой правый, нужно сравним их координаты по x и обменяем значения, если нужно. Рисуя этот отрезок, повторяя процедуру для каждой строки - получаем треугольник. Рассматривая более подробно пересечения прямой y = sy (текущей строки) и стороны треугольника, например AB, Получим уравнение прямой AB в форме x = k*y+b: x = A.x+(y-A.y)*(B.x-A.x)/(B.y-A.y) Теперь надо подставить известное для текущей прямой значение y = sy: x = A.x+(sy-A.y)*(B.x-A.x)/(B.y-A.y) Для других сторон пересечение ищется совершенно точно так же. Например: // ... // здесь сортируем вершины (A,B,C) // ... for sy = A.y to C.y begin x1 = A.x + (sy - A.y) * (C.x - A.x) / (C.y - A.y); if (sy < B.y)Then x2 = A.x + (sy - A.y) * (B.x - A.x) / (B.y - A.y); else x2 = B.x + (sy - B.y) * (C.x - B.x) / (C.y - B.y); if (x1 > x2) Then begin tmp = x1; x1 = x2; x2 = tmp; end; drawHorizontalLine(sy, x1, x2); end; Необходимо защититься от случая, когда B.y = C.y - в этом (и только этом, потому как если C.y = A.y, то треугольник пустой и рисовать его не нужно, или можно рисовать горизонтальную линию; а если B.y = A.y, то sy >= A.y и до деления на B.y - A.y не дойдет) случае произойдет попытка деления на ноль. // ... // здесь сортируем вершины (A,B,C) // ... for sy = A.y to C.y begin x1 = A.x + (sy - A.y) * (C.x - A.x) / (C.y - A.y); if (sy < B.y) x2 = A.x + (sy - A.y) * (B.x - A.x) / (B.y - A.y); else begin if (C.y == B.y) x2 = B.x; else x2 = B.x + (sy - B.y) * (C.x - B.x) / (C.y - B.y); end; if (x1 > x2)Then begin tmp = x1; x1 = x2; x2 = tmp; drawHorizontalLine(sy, x1, x2); end; // ... Здесь drawHorizontalLine(sy, x1, x2) - горизонтальная линия. Её создание не представляет сложности и код будетвыглядеть так. //... For i:=x1 to x2 do PutPixel(i,sy,Color); //... 6. Программа unit graph3; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DXClass, DXDraws, StdCtrls,graph, Menus,graph3D,figures, Buttons; const Mode:Word=0; type TLab = class(TForm) Vid: TDXDraw; Timer: TDXTimer; Enter: TButton; Menu: TMainMenu; N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; N7: TMenuItem; N8: TMenuItem; N9: TMenuItem; OpenDialog: TOpenDialog; SaveDialog: TSaveDialog; N10: TMenuItem; Space: TButton; Box1: TComboBox; Label1: TLabel; OK: TButton; Cancel: TButton; Label6: TLabel; BCube: TBitBtn; BSide: TBitBtn; Box6: TComboBox; Label7: TLabel; procedure FormCreate(Sender: TObject); procedure TimerTimer(Sender: TObject; LagCount: Integer); procedure VidMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure EnterClick(Sender: TObject); procedure N3Click(Sender: TObject); procedure N4Click(Sender: TObject); procedure N2Click(Sender: TObject); procedure N9Click(Sender: TObject); procedure N10Click(Sender: TObject); procedure SpaceClick(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure CancelClick(Sender: TObject); procedure OKClick(Sender: TObject); procedure N8Click(Sender: TObject); procedure BCubeClick(Sender: TObject); procedure BSideClick(Sender: TObject); procedure N6Click(Sender: TObject); private public end; var Lab: TLab; implementation {$R *.DFM} const ScreenX:Word=640; ScreenY:Word=480; x1:integer=0; y1:integer=0; White=$FFFFFF; View:Boolean=False; Figure:Word=1; Accept:Boolean=True; sv:Word=0; var c:char;S,SS,TMP:PPl;t:PTexture; CS,CO,CC,CSc,CL:Word;Rot:TRot; x0,y0,x2,y2:integer;r:Single; Blue,Red,Yelow,M,N,SC:Word; Keys:array[1..255]of Boolean; Input:array[1..12]of procedure (x,y:integer;var E:Boolean); Bol:Boolean;Option:array[1..5] of String; o:array[1..MaxSide]of TPoint; w:array[1..2]of TPoint;tmp_o:TPoint; cx,cy:Word;oc:TPoint;ClicCub:array[0..MaxSide]of Boolean; procedure LoadObject(Name:String;var Obj:PObj); var f1:file of TPoint; a:TSides; f2:file of Word; S,Tmp:TPoint;i,j:word;Name2:String; B:Boolean; begin For i:=1 to Length (Name)-4 do begin Name2:=Name2+Name[i]; end; Name:=Name2; Assign(f2,Name+'.res'); Reset(f2); Read(f2,Obj^.Count); close(f2); Assign(f1,Name+'.dat'); Reset(f1); Read(f1,Obj^.o); For i:=1 to Obj^.Count do New(Obj^.Side[i],Create(Obj^.o.x,Obj^.o.y,Obj^.o.z,0,0,0,a)); For i:=1 to Obj^.Count do begin inc(CS); if(i mod 2<>0)Then T:=ColorText(RGB(100+Random(155),100+Random(155),100+Random(155)),GMT) else T:=T; Obj^.Side[i]^.Texture:=T; Obj^.Side[i]^.Mode:=Mode; Obj^.Side[i]^.Alpha:=0; Read(f1,S); For j:=1 to 3 do begin Read(f1,S); Obj^.Side[i]^.S[j]:=S; SS^[i,j]:=S; end; end; close(f1); end; procedure SaveObject(Name:String;var Obj:PObj); var f1:file of TPoint; f2:file of Word;B:Boolean; S:TPoint;i,j:word;Name2:String; begin B:=False; For i:=1 to Length(Name) do if(Name[i]='.')Then B:=True; if(B=True)Then begin For i:=1 to Length(Name)-4 do begin Name2:=Name2+Name[i]; end; Name:=Name2; end; Assign(f2,Name+'.res'); Rewrite(f2); Reset(f2); Write(f2,Obj^.Count); close(f2); Assign(f1,Name+'.dat'); Rewrite(f1); Reset(f1); Write(f1,Obj^.o); For i:=1 to Obj^.Count do begin Obj^.Side[i]^.o:=tmp_o; S:=Obj^.Side[i]^.o; Write(f1,S); For j:=1 to 3 do begin S:=Obj^.Side[i]^.S[j]; Write(f1,S); end; end; close(f1); end; procedure CreateTMP(var Obj:PObj); var i,j,k:Word; begin Obj^.o.x:=0;Obj^.o.y:=0;Obj^.o.z:=100; For i:=1 to Obj^.Count do begin tmp_o:=Obj^.Side[i]^.o; Obj^.Side[i]^.o:=o[i]; For j:=1 to 3 do Obj^.Side[i]^.S[j]:=S^[i,j]; end; end; procedure ShowSide; var i,j,k,cx,cy:Word;tmp:TPoint; begin Lab.Vid.Surface.Fill(0); myForm(GetMaxX,GetMaxY); For i:=1 to CS do begin Line(Trunc(SS^[i,1].x),Trunc(SS^[i,1].y),Trunc(SS^[i,2].x),Trunc(SS^[i,2].y),White); Line(Trunc(SS^[i,2].x),Trunc(SS^[i,2].y),Trunc(SS^[i,3].x),Trunc(SS^[i,3].y),White); Line(Trunc(SS^[i,3].x),Trunc(SS^[i,3].y),Trunc(SS^[i,1].x),Trunc(SS^[i,1].y),White); Line(Trunc(SS^[i,1].x),Trunc(SS^[i,1].z),Trunc(SS^[i,2].x),Trunc(SS^[i,2].z),White); Line(Trunc(SS^[i,2].x),Trunc(SS^[i,2].z),Trunc(SS^[i,3].x),Trunc(SS^[i,3].z),White); Line(Trunc(SS^[i,3].x),Trunc(SS^[i,3].z),Trunc(SS^[i,1].x),Trunc(SS^[i,1].z),White); Line(Trunc(SS^[i,1].z*r),Trunc(SS^[i,1].y),Trunc(SS^[i,2].z*r),Trunc(SS^[i,2].y),White); Line(Trunc(SS^[i,2].z*r),Trunc(SS^[i,2].y),Trunc(SS^[i,3].z*r),Trunc(SS^[i,3].y),White); Line(Trunc(SS^[i,3].z*r),Trunc(SS^[i,3].y),Trunc(SS^[i,1].z*r),Trunc(SS^[i,1].y),White); if(ClicCub[i]=True)Then begin Line(Trunc(SS^[i,1].z),Trunc(SS^[i,1].y),Trunc(SS^[i,2].z),Trunc(SS^[i,1].y),White); Line(Trunc(SS^[i,2].z),Trunc(SS^[i,1].y),Trunc(SS^[i,1].z),Trunc(SS^[i,3].y),White); end; end; S[CS]:=SS[CS]; cx:=GMX div 2; cy:=GMY div 2+1; For i:=1 to 3 do begin S^[CS,i].x:=S^[CS,i].x-cx+dF; S^[CS,i].y:=cy-S^[CS,i].y-dF; S^[CS,i].z:=S^[CS,i].z-cx-dF; end; end; procedure CreateSide(var Obj:PObj); var cx,cy,i,j,k:Word; begin r:=1; For i:=1 to Obj^.Count do S[i]:=Obj^.Side[i]^.S; TMP:=S; Lab.Vid.Surface.Fill(0); myForm(GetMaxX,GetMaxY); cx:=GMX div 2; cy:=GMY div 2+1; For j:=1 to CS do For i:=1 to 3 do begin TMP^[j,i].x:=TMP^[j,i].x-cx+dF; TMP^[j,i].y:=cy-TMP^[j,i].y-dF; TMP^[j,i].z:=TMP^[j,i].z-cx-dF; end; For i:=1 to CS do begin Line(Trunc(TMP^[i,1].x),Trunc(TMP^[i,1].y),Trunc(TMP^[i,2].x),Trunc(TMP^[i,2].y),White); Line(Trunc(TMP^[i,2].x),Trunc(TMP^[i,2].y),Trunc(TMP^[i,3].x),Trunc(TMP^[i,3].y),White); Line(Trunc(TMP^[i,3].x),Trunc(TMP^[i,3].y),Trunc(TMP^[i,1].x),Trunc(TMP^[i,1].y),White); Line(Trunc(TMP^[i,1].x),Trunc(TMP^[i,1].z),Trunc(TMP^[i,2].x),Trunc(TMP^[i,2].z),White); Line(Trunc(TMP^[i,2].x),Trunc(TMP^[i,2].z),Trunc(TMP^[i,3].x),Trunc(TMP^[i,3].z),White); Line(Trunc(TMP^[i,3].x),Trunc(TMP^[i,3].z),Trunc(TMP^[i,1].x),Trunc(TMP^[i,1].z),White); Line(Trunc(TMP^[i,1].z*r),Trunc(TMP^[i,1].y),Trunc(TMP^[i,2].z*r),Trunc(TMP^[i,2].y),White); Line(Trunc(TMP^[i,2].z*r),Trunc(TMP^[i,2].y),Trunc(TMP^[i,3].z*r),Trunc(TMP^[i,3].y),White); Line(Trunc(TMP^[i,3].z*r),Trunc(TMP^[i,3].y),Trunc(TMP^[i,1].z*r),Trunc(TMP^[i,1].y),White); end; Flip(Lab.Vid); end; procedure LoadSide(var Obj:PObj); var i,j,k:Word;TMP:PPL; begin r:=1; For i:=1 to Obj^.Count do S[i]:=Obj^.Side[i]^.S; SS^:=S^; Lab.Vid.Surface.Fill(0); myForm(GetMaxX,GetMaxY); For j:=1 to CS do For i:=1 to 3 do
Страницы: 1, 2, 3, 4, 5
|