IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> заливка граней тетраэдра
сообщение
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Объясните пожалуйста, как на основании ниже приведённой программы закрасить грани тетраэдра ( обычным способом, с помощью 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;

Xt := tetr[p*3] * COS(Y) - tetr[p*3+2] * SIN(Y);
Zt := tetr[p*3] * SIN(Y) + tetr[p*3+2] * COS(Y);
tetr[p*3] := Xt;
tetr[p*3+2] := Zt;

Xt := tetr[p*3] * COS(Z) - tetr[p*3+1] * SIN(Z);
Yt := tetr[p*3] * SIN(Z) + tetr[p*3+1] * COS(Z);
tetr[p*3] := Xt;
tetr[p*3+1] := Yt;
end;
end;


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.





Сообщение отредактировано: 18192123 -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Perl. Just code it!
******

Группа: Пользователи
Сообщений: 4 100
Пол: Мужской
Реальное имя: Андрей

Репутация: -  44  +


FloodFill'ом не получится, у тебя линии не соединены, между ними есть промежутки ... Собственно эту проблему я думаю и надо решить, а залить-то уже не сложно.

Например вот такой код:

SetFillStyle(SolidFill, Red);
FloodFill(260, 295, white);


Должен заливать только верхнюю грань, но так как какая-то из пар линий принадлежащих этому ребру пересекаются не в одной точке, точнее говоря отрезки эти не пересекаются, по этому не создают замкнутого пространства которое можно залить, этого не происходит


--------------------
perl -e 'print for (map{chr(hex)}("4861707079204E6577205965617221"=~/(.{2})/g)), "\n";'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(klem4 @ 25.04.2007 21:51) *

FloodFill'ом не получится, у тебя линии не соединены, между ними есть промежутки ... Собственно эту проблему я думаю и надо решить, а залить-то уже не сложно.

Например вот такой код:

SetFillStyle(SolidFill, Red);
FloodFill(260, 295, white);


Должен заливать только верхнюю грань, но так как какая-то из пар линий принадлежащих этому ребру пересекаются не в одной точке, точнее говоря отрезки эти не пересекаются, по этому не создают замкнутого пространства которое можно залить, этого не происходит

и как быть? в том числе с остальными гранями?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
и как быть?
Отрисовывать не ребра, а грани... Причем не с помощью Line, а с помощью FillPoly, которая закрашивает полигон...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Уникум
*******

Группа: Пользователи
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(klem4 @ 25.04.2007 21:51) *

FloodFill'ом не получится, у тебя линии не соединены, между ними есть промежутки

klem4, скажи, как так может случиться, что ты проводишь линии между тремя точками, и эти линии не пересекаются?.. blink.gif Я не могу представить себе такую ситуацию..

Конечно, Марина в своем репертуаре - наворочала так, что конь ногу сломит.. Задавать координаты таким образом - это все равно, что назвать своих детей номерами, а потом еще домашних животных в эту же нумерацию свалить.. Если что-то советовать, то нужно советовать именно как это исправить. А точки - они точки и есть. Хотя Марина их и вычисляет по нескольку раз, все равно должно получиться замкнутое пространство. У меня, кстати, так все и отрисовалось. klem4, у тебя не так? и ты вставлял код заливки после процедуры Draw(15)? Я не понимаю, почему.. странно...
Стирать нужно кодом:
  SetFillStyle(SolidFill, Black);
FloodFill(260, 295, Black);

- вставить после вторго вызова Draw.

Вот только работает это страшно медленно... Поэтому все же лучше использовать не FloodFill, а FillPoly (присоединяюсь к словам volvo - но, повторяю, только для ускорения и упрощения). Помимо прочего, отпадет неопределенность с выбором точки начала заполнения (очень существенно!!).

Еще один вопрос - как выделить верхние грани. Но мне кажется, Марина уже интересовалась им..


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

Репутация: -  20  +


Чтоб закрасить грань, надо внесть в прогу такое понятие. Т.е. заменить твой массив 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;


Правда для заливки тебе эта процедура не понадобится smile.gif
Твои следующие шаги: После поворота всех точек необходимо найти расстояние от наблюдателя до грани (до средней точки просто). Далее отрисовываешь все грани, начиная с самой удаленной. Самую дальнюю, кстати, можно вообще не рисовать, т.к. из 4-х граней в 1 момент может быть видно только 3.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


решила сделать сначала... добилась заливки граней, но тетраэдра у меня не получается.... я полагаю, дело в неправильном соединении точек грани, это здесь:

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

begin
with fg do begin
npixel:=4;
plosk:=4;

mass1[1].x3d:=S;mass1[1].y3d:=0;mass1[1].z3d:=0;
mass1[2].x3d:=0;mass1[2].y3d:=S;mass1[2].z3d:=0;
mass1[3].x3d:=-S;mass1[3].y3d:=0;mass1[3].z3d:=0;
mass1[4].x3d:=0;mass1[4].y3d:=-S;mass1[4].z3d:=0;

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;

end;

rotate(rt,0.25,1);
preobraz(fg,rt);
rotate(rt,0.13,2);

repeat

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.




Сообщение отредактировано: 18192123 -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

Репутация: -  20  +


Цитата(18192123 @ 26.04.2007 17:11) *

решила сделать сначала... добилась заливки граней, но тетраэдра у меня не получается....

Если хвататься за разные исходники, бросать темы и никого не слушать, то вряд ли что-то получится.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(Malice @ 26.04.2007 19:10) *

Если хвататься за разные исходники, бросать темы и никого не слушать, то вряд ли что-то получится.

прошу прощения, если кого-то обидела, но я использую то, что мне наиболее понятно.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

Репутация: -  20  +


Цитата(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.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(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;





спасибо большое! вроде разобралась, только не понятен вот этот фрагмент. Объясни пожалуйста.

Сообщение отредактировано: 18192123 -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

Репутация: -  20  +


Цитата(18192123 @ 26.04.2007 21:11) *

спасибо большое! вроде разобралась, только не понятен вот этот фрагмент. Объясни пожалуйста.

Это как раз сортировка: берем 3 координаты Z вершин грани после поворота и делим на 3, получает среднее расстояние до грани. Сравниваем по таким значениям все и сортируем.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 29.10.2020 12:15
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name