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

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

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

> заливка граней тетраэдра
18192123
сообщение 25.04.2007 17:23
Сообщение #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 - 25.04.2007 17:24
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов(1 - 11)
klem4
сообщение 25.04.2007 20:51
Сообщение #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 
 К началу страницы 
+ Ответить 
18192123
сообщение 25.04.2007 21:49
Сообщение #3


Профи
****

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

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


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

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

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

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


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

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


Гость






Цитата
и как быть?
Отрисовывать не ребра, а грани... Причем не с помощью Line, а с помощью FillPoly, которая закрашивает полигон...
 К началу страницы 
+ Ответить 
Lapp
сообщение 26.04.2007 0:48
Сообщение #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 
 К началу страницы 
+ Ответить 
Malice
сообщение 26.04.2007 9:37
Сообщение #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 
 К началу страницы 
+ Ответить 
18192123
сообщение 26.04.2007 16:11
Сообщение #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 - 26.04.2007 16:12
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Malice
сообщение 26.04.2007 18:10
Сообщение #8


Профи
****

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

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


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

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

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


Профи
****

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

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


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

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

прошу прощения, если кого-то обидела, но я использую то, что мне наиболее понятно.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Malice
сообщение 26.04.2007 19:53
Сообщение #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 
 К началу страницы 
+ Ответить 
18192123
сообщение 26.04.2007 20:11
Сообщение #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 - 26.04.2007 20:12
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Malice
сообщение 26.04.2007 20:26
Сообщение #12


Профи
****

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

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


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

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

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

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

 



- Текстовая версия 20.07.2025 18:39
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"