Объясните пожалуйста, как на основании ниже приведённой программы закрасить грани тетраэдра ( обычным способом, с помощью FloodFill или SetFillStyle или что-то в этом роде..)?
uses Graph,crt; const tetr: array[0..11] of real = (1,0,0, 0,1,0, 0,0,1, -0.5,-0.5,-0.5); line_: array[0..11] of integer = (0,1, 0,2, 0,3, 1,2, 1,3, 2,3); var xt,yt,zt:real; x,y,z:real; sx,sy,sx1,sy1,p,zoom: integer;
procedure draw(color:byte); begin for p:=0 to 5 do begin sx:=round(zoom*tetr[line_[p*2]*3])+260; sy:=round(zoom*tetr[line_[p*2]*3+1])+300; sx1:=round(zoom*tetr[line_[p*2+1]*3])+260; sy1:=round(zoom*tetr[line_[p*2+1]*3+1])+300; setcolor(color); line(SX,SY,sx1,sy1); end; end;
procedure calc; begin for p:=0 to 3 do begin Yt := tetr[p*3+1] * COS(X) - tetr[p*3+2] * SIN(X); Zt := tetr[p*3+1] * SIN(X) + tetr[p*3+2] * COS(X); tetr[p*3+1] := Yt; tetr[p*3+2] := Zt;
var gd,gm:integer; t:char; begin gd:=detect; initgraph(gd,gm,''); Z := 0.1; Y := 0.1; X := 0.1; zoom:=70;
repeat draw(15); delay(20000); draw(0); calc; if keypressed then begin t:=readkey; case t of '=':zoom:=zoom+1; {+} '-': zoom:=zoom-1;{-} end; end until t=#13;; closegraph; end.
klem4
26.04.2007 0:51
FloodFill'ом не получится, у тебя линии не соединены, между ними есть промежутки ... Собственно эту проблему я думаю и надо решить, а залить-то уже не сложно.
Должен заливать только верхнюю грань, но так как какая-то из пар линий принадлежащих этому ребру пересекаются не в одной точке, точнее говоря отрезки эти не пересекаются, по этому не создают замкнутого пространства которое можно залить, этого не происходит
18192123
26.04.2007 1:49
Цитата(klem4 @ 25.04.2007 21:51)
FloodFill'ом не получится, у тебя линии не соединены, между ними есть промежутки ... Собственно эту проблему я думаю и надо решить, а залить-то уже не сложно.
Должен заливать только верхнюю грань, но так как какая-то из пар линий принадлежащих этому ребру пересекаются не в одной точке, точнее говоря отрезки эти не пересекаются, по этому не создают замкнутого пространства которое можно залить, этого не происходит
и как быть? в том числе с остальными гранями?
volvo
26.04.2007 1:59
Цитата
и как быть?
Отрисовывать не ребра, а грани... Причем не с помощью Line, а с помощью FillPoly, которая закрашивает полигон...
Lapp
26.04.2007 4:48
Цитата(klem4 @ 25.04.2007 21:51)
FloodFill'ом не получится, у тебя линии не соединены, между ними есть промежутки
klem4, скажи, как так может случиться, что ты проводишь линии между тремя точками, и эти линии не пересекаются?.. Я не могу представить себе такую ситуацию..
Конечно, Марина в своем репертуаре - наворочала так, что конь ногу сломит.. Задавать координаты таким образом - это все равно, что назвать своих детей номерами, а потом еще домашних животных в эту же нумерацию свалить.. Если что-то советовать, то нужно советовать именно как это исправить. А точки - они точки и есть. Хотя Марина их и вычисляет по нескольку раз, все равно должно получиться замкнутое пространство. У меня, кстати, так все и отрисовалось. klem4, у тебя не так? и ты вставлял код заливки после процедуры Draw(15)? Я не понимаю, почему.. странно... Стирать нужно кодом:
Вот только работает это страшно медленно... Поэтому все же лучше использовать не FloodFill, а FillPoly (присоединяюсь к словам volvo - но, повторяю, только для ускорения и упрощения). Помимо прочего, отпадет неопределенность с выбором точки начала заполнения (очень существенно!!).
Еще один вопрос - как выделить верхние грани. Но мне кажется, Марина уже интересовалась им..
Malice
26.04.2007 13:37
Чтоб закрасить грань, надо внесть в прогу такое понятие. Т.е. заменить твой массив line_, в котором точки сгруппированы по 2, на массив граней, где группировка по 3 точки. Вот так например:
grn: array [0..11] of integer = (0,1,2, 0,1,3, 0,2,3, 1,2,3);
В этом случае процедура отрисоки поменяется например так:
procedure draw(color:byte); var j,p:integer; begin setcolor(color); for p:=0 to 3 do begin sx1:=round(zoom*tetr[grn[p*2]*3])+260; sy1:=round(zoom*tetr[grn[p*2]*3+1])+300; for j:=1 to 2 do begin sx:=round(zoom*tetr[grn[p*2+j]*3])+260; sy:=round(zoom*tetr[grn[p*2+j]*3+1])+300; line(SX,SY,sx1,sy1); sx1:=sx; sy1:=sy; end; end; end;
Правда для заливки тебе эта процедура не понадобится Твои следующие шаги: После поворота всех точек необходимо найти расстояние от наблюдателя до грани (до средней точки просто). Далее отрисовываешь все грани, начиная с самой удаленной. Самую дальнюю, кстати, можно вообще не рисовать, т.к. из 4-х граней в 1 момент может быть видно только 3.
18192123
26.04.2007 20:11
решила сделать сначала... добилась заливки граней, но тетраэдра у меня не получается.... я полагаю, дело в неправильном соединении точек грани, это здесь:
with gran[1] do begin a:=1;b:=2;c:=4;cl:=9;end; with gran[2] do begin a:=2;b:=4;c:=3;cl:=9;end; with gran[3] do begin a:=3;b:=4;c:=1;cl:=9;end; with gran[4] do begin a:=1;b:=2;c:=3;cl:=9;end;
здесь а, b, с - номера точек для каждой грани, а с помощью таких преобразований я и пытаюсь задать грани и их цвет.
вот вся программа:
Program Tetr_5; Uses crt,graph; Type Tetr=record mass1:array [1..4] of record x3d,y3d,z3d:real; x2,y2:integer; xold,yold:integer; end;
gran:array [1..4] of record a,b,c:integer; cl:integer; end; npixel:integer; plosk:integer; end; matr=array [1..4,1..4] of real; const S=150;
procedure otobragenie(var f:tetr); var n:integer; t:array [1..3] of pointtype; const EYEY=400; EYEL=200; begin with f do for n:=1 to npixel do with mass1[n] do begin xold:=x2;yold:=y2; x2:=trunc(x3d*EYEL/(z3d-EYEY)); y2:=trunc(y3d*EYEL/(z3d-EYEY)); end; setcolor(0); setfillstyle(1,0); with f do for n:=1 to plosk do begin t[1].x:=300+mass1[gran[n].a].xold;t[1].y:=200-mass1[gran[n].a].yold; t[2].x:=300+mass1[gran[n].b].xold;t[2].y:=200-mass1[gran[n].b].yold; t[3].x:=300+mass1[gran[n].c].xold;t[3].y:=200-mass1[gran[n].c].yold; fillpoly(3,t); end; setcolor(0); with f do for n:=1 to plosk do begin setfillstyle(1,gran[n].cl); t[1].x:=300+mass1[gran[n].a].x2;t[1].y:=200-mass1[gran[n].a].y2; t[2].x:=300+mass1[gran[n].b].x2;t[2].y:=200-mass1[gran[n].b].y2; t[3].x:=300+mass1[gran[n].c].x2;t[3].y:=200-mass1[gran[n].c].y2; fillpoly(3,t); end; end;
procedure preobraz(var f:tetr;m:matr); var nx,ny,nz:real; n:integer; begin for n:=1 to f.npixel do with f.mass1[n] do begin nx:=m[1,1]*x3d+m[1,2]*y3d+m[1,3]*z3d+m[1,4]; ny:=m[2,1]*x3d+m[2,2]*y3d+m[2,3]*z3d+m[2,4]; nz:=m[3,1]*x3d+m[3,2]*y3d+m[3,3]*z3d+m[3,4]; x3d:=nx;y3d:=ny;z3d:=nz; end; end;
procedure smeshenie(var mm:matr); var n,m:integer; begin for n:=1 to 4 do for m:=1 to 4 do if (n<>m) then mm[n,m]:=0 else mm[n,m]:=1; end;
procedure rotate(var m:matr;a:real;n:integer); var ax1,ax2:integer; begin smeshenie(m); ax1:=n+1;if ax1=4 then ax1:=1; ax2:=ax1+1;if ax2=4 then ax2:=1; m[ax1,ax1]:=cos(a); m[ax1,ax2]:=-sin(a); m[ax2,ax1]:=sin(a); m[ax2,ax2]:=cos(a); end;
var drv,mode:integer; c:char; fg:tetr; rt:matr; begin drv:=DETECT; mode:=VGAHI; initgraph(drv,mode,''); if (GraphResult=grOk) then
with gran[1] do begin a:=1;b:=2;c:=4;cl:=9;end; with gran[2] do begin a:=2;b:=4;c:=3;cl:=9;end; with gran[3] do begin a:=3;b:=4;c:=1;cl:=9;end; with gran[4] do begin a:=1;b:=2;c:=3;cl:=9;end;
otobragenie(fg); delay(10000); preobraz(fg,rt); if (keypressed) then begin c:=readkey; end else c:=' '; until c=#27; closegraph; end else begin writeln; writeln('Error initialize !!!'); end; end.
Malice
26.04.2007 22:10
Цитата(18192123 @ 26.04.2007 17:11)
решила сделать сначала... добилась заливки граней, но тетраэдра у меня не получается....
Если хвататься за разные исходники, бросать темы и никого не слушать, то вряд ли что-то получится.
18192123
26.04.2007 23:06
Цитата(Malice @ 26.04.2007 19:10)
Если хвататься за разные исходники, бросать темы и никого не слушать, то вряд ли что-то получится.
прошу прощения, если кого-то обидела, но я использую то, что мне наиболее понятно.
Malice
26.04.2007 23:53
Цитата(18192123 @ 26.04.2007 20:06)
прошу прощения, если кого-то обидела, но я использую то, что мне наиболее понятно.
Да не вопрос.. Просто не понял, зачем браться разбираться с новым исходником, когда в той осталось чуть-чуть.
Вот немного модернизировал первоначальный вариант (добавил собственно сортировку и вывод):
procedure draw(color:byte); var i,k,j,p:integer; x:real; Tr: array[1..3] of PointType; begin setcolor(color); setfillstyle (1,4); for i:=0 to 2 do for j:=i+1 to 3 do begin z:=(tetr[grn[i*3]*3+2]+tetr[grn[i*3+1]*3+2]+tetr[grn[i*3+2]*3+2])/3; x:=(tetr[grn[j*3]*3+2]+tetr[grn[j*3+1]*3+2]+tetr[grn[j*3+2]*3+2])/3; if z>x then for p:=0 to 2 do begin k:= grn[i*3+p];grn[i*3+p]:=grn[j*3+p]; grn[j*3+p]:=k; end; end; for p:=1 to 3 do begin for j:=0 to 2 do begin tr[j+1].x:=round(zoom*tetr[grn[p*3+j]*3])+260; tr[j+1].y:=round(zoom*tetr[grn[p*3+j]*3+1])+300; end; fillpoly (3,tr); end; end;
Стирать через draw(0); уже нельзя, можно вызывать вместо этого cleardevice.
18192123
27.04.2007 0:11
Цитата(Malice @ 26.04.2007 20:53)
z:=(tetr[grn[i*3]*3+2]+tetr[grn[i*3+1]*3+2]+tetr[grn[i*3+2]*3+2])/3; x:=(tetr[grn[j*3]*3+2]+tetr[grn[j*3+1]*3+2]+tetr[grn[j*3+2]*3+2])/3; if z>x then for p:=0 to 2 do begin k:= grn[i*3+p];grn[i*3+p]:=grn[j*3+p]; grn[j*3+p]:=k; end;
спасибо большое! вроде разобралась, только не понятен вот этот фрагмент. Объясни пожалуйста.
Malice
27.04.2007 0:26
Цитата(18192123 @ 26.04.2007 21:11)
спасибо большое! вроде разобралась, только не понятен вот этот фрагмент. Объясни пожалуйста.
Это как раз сортировка: берем 3 координаты Z вершин грани после поворота и делим на 3, получает среднее расстояние до грани. Сравниваем по таким значениям все и сортируем.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.