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

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

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

2 страниц V < 1 2  
 Ответить  Открыть новую тему 
> трехмерное пространство, найти радиус
сообщение
Сообщение #21


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

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

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


lapp, а пост # 15 ты учел ?


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





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

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


Цитата(klem4 @ 26.04.2006 11:25) *
lapp, а пост # 15 ты учел ?

тогда можете проверить етот код

uses crt;
type InfoSphere=record
x,y,z,r:real;
end;
const n=10;
var InfoSp:InfoSphere;
f:text;
i:integer;
Spheri: array[1..n] of InfoSphere;
Rnew,Xnew,Ynew,Znew:real;

function Lenght(x0,y0,z0,x1,y1,z1:real):real;
begin
Lenght:=sqrt(sqr(x0-x1)+sqr(y0-y1)+sqr(z0-z1));
end;


procedure SearchMinSpher(x0,y0,z0,r0,x1,y1,z1,r1:real);
var L:real;
begin
L:=Lenght(x0,y0,z0,x1,y1,z1);
if (L=0) then
begin
Xnew:=x0;
Ynew:=y0;
Znew:=z0;
if (r1>r0) then
begin
Rnew:=r1;
end
else
begin
Rnew:=r0;
end;
end
else
begin
if (r1>r0) and ((r1-r0)>=L) then
begin
Rnew:=r1;
Xnew:=x1;
Ynew:=y1;
Znew:=z1;
end;
if (r0>r1) and ((r0-r1)>=L) then
begin
Rnew:=r0;
Xnew:=x0;
Ynew:=y0;
Znew:=z0;
end;
Rnew:=(r0+r1+L)/2;
Xnew:=(Rnew-r0)*(x1-x0)/L+x0;
Ynew:=(Rnew-r0)*(y1-y0)/L+y0;
Znew:=(Rnew-r0)*(z1-z0)/L+z0;

end;
end;

begin
assign(f,'3_input.txt');
reset(f); {otkrivaem file}
with InfoSp do
begin
for i:=0 to 4*n do
begin
read(f,Spheri[i div 4].x);
read(f,Spheri[i div 4].y);
read(f,Spheri[i div 4].z);
read(f,Spheri[i div 4].r);
end;
{
zapolnili massiv iz file
}
Rnew:=Spheri[1].r;
Xnew:=Spheri[1].x;
Ynew:=Spheri[1].y;
Znew:=Spheri[1].z;
for i:=2 to n do
begin
SearchMinSpher(Xnew,Ynew,Znew,Rnew,Spheri[i].x,Spheri[i].x,Spheri[i].x,Spheri[i].x);
end;

end;
close(f);
end.


Теги !
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #23


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

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

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


Цитата(klem4 @ 26.04.2006 7:25) *

lapp, а пост # 15 ты учел ?

Да, klem4, учел. Вообще-то хотя бы минимум комментариев, просто как жест вежливости и уважения к читающим, не помешал бы.. Да, я просмотрел программу, потом функцию из поста №15, сравнил, разобрался, что именно ты исправлял, и именно поэтому написал, что тебе следовало бы обратить чуть больше внимания на пост Бравого генерала. Ну и, кроме того - ты просил тестовые данные? Я тебе их дал. Ты проверил? Рекомендую проверить не только на программе, но и на листочке, с рисунком. Тогда ты поймешь, о чем говорил Бравый, и о чем я сейчас толкую. Ок? smile.gif

bairt, тебя нельзя упрекнуть в отсутствии комментариев - в твоей проге есть один! smile.gif Но этого все же недостаточно.. sad.gif Я очень извиняюсь, но рыскать глазами, ослеживая переменные, даже не представляя сначала, что же хотел сказать автор - ну, согласитесь, это носненс. Ну ладно еще, если бы алгоритм был известен. Тут же задача именно на составление алгоритма, а не программы! А еще лучше - дать параллельно краткое описание алгоритма. Ну, кто со мной не согласится? Ладно унимаюсь..

Короче, одного взгляда близорукого человека издалека на обе проги достаточно, чтобы сказать, что они не могут быть верными. Алгоритм, насколько я сейчас понимаю, гораздо сложнее, и к тому же он включает громоздкие математические вычисления. Сейчас я налью себе чаю smile.gif и попробую описать, чего мне удалось надумать..

Если, конечно, кто нибудь не выложит верное решение раньше (или klem4 или bairt не докажут, что они правы). smile.gif


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


Новичок
*

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

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


Цитата
lapp, а пост # 15 ты учел ?

smile.gif klem4, ты так сказал, как будто после того поста решение КАРДИНАЛЬНО изменилось. Да, охватывающая сфера должна охватывать сферы, а не их центры, но сам костяк этого алгоритма неверен.
Цитата
Алгоритм, насколько я сейчас понимаю, гораздо сложнее, и к тому же он включает громоздкие математические вычисления.

Во-во!
Цитата
и для наглядности сначала делал с окружностями, типа в 2D

Вобщем, чтобы с тем неправильным алгоритмом было все ясно, вот эта программа - тот же алгоритм только в 2D, чтобы можно было проверить визуально. Бывают конечно случаи, когда охватывающая окружность охватывает ВСЕ окружности, но часто бывает, что сферы "вылазят" за охватывающую сферу, что и доказывает неправильность алгоритма.
Uses
Crt, Graph;

Type
Ball = record
x,y,r: Real
end;

Const
n = 10;

Var
gd,gm: Integer;
i,j,x,y,z: Byte;
b: Array [1..n] of Ball;
l,l0,d,dx,dy,x0,y0: Real;
c: Ball;
ch: char;

Function Ohvat(a,b: Ball): Real;
var
i: Byte;
begin
Ohvat:=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))+a.r+b.r
end; {Ohvat}

{****************************************************************************}

Begin
Randomize;

for i:=1 to n
do begin
b[i].x:=Random(400)+120;
b[i].y:=Random(300)+90;
b[i].r:=Random(50);
end;

InitGraph(gd,gm,'');

l:=0;
for i:=1 to n-1
do for j:=i+1 to n
do begin
l0:=Ohvat(b[i],b[j]);
if l0 > l
then begin
l:=l0;
x:=i;
y:=j
end
end;
dx:=b[y].x-b[x].x;
dy:=b[y].y-b[x].y;
d:=sqrt(sqr(dx)+sqr(dy));
c.r:=Ohvat(b[x],b[y])/2;
c.x:=b[x].x + (c.r-b[x].r)*(dx/d);
c.y:=b[x].y + (c.r-b[x].r)*(dy/d);

for i:=1 to n
do Circle(Round(b[i].x),Round(b[i].y),Round(b[i].r));
setcolor(2);
Circle(Round(c.x),Round(c.y),Round(c.r));

ReadKey;

CloseGraph
End.


Добавлено позже:

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


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

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

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


Да, теперь я понял, что был не прав, извиняюсь.

И всеже мне кажется что решение должно быть простым, еще одна идея есть, завтра сделаю.

Сообщение отредактировано: klem4 -


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


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

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

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


Цитата(klem4 @ 26.04.2006 19:40) *

Да, теперь я понял, что был не прав, извиняюсь.
И всеже мне кажется что решение должно быть простым, еще одна идея есть, завтра сделаю.

Извиняться тут абсолютно не за что smile.gif
O'kay, делай.
Я пока подожду постить свое решение.


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


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

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

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


Выполняю обещанное - публикую анонсированное мной в одном из предыдущих постов решение задачи. То есть не решение, а только алгоритм в самом общем виде. Более того, в нем присутствуют нерешенные математические выражения. Программый код к этой задаче я стал бы писать только под дулом банкомата, и желательно как можно более крупного калибра smile.gif.

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

Рассмотрим двумерный случай: ищем окружность минимального радиуса, охватывающую заданный конечный набор кругов. Проведем небольшое исследование, по традиции начинаемое словами: предположим, что задача решена, и минимальная охватывающая окружность построена...

В этом месте небольшое лирическое отступление. Два утверждения:

1. На плоскости в общем случае можно провести одну и только одну окружность, касающуюся трех данных (окружность Апполония, ОА) так, чтобы все три данные оказались внутри нее (в дальнейшем, кроме оговоренного, под "касанием" я буду понимать именно такое касание). Иногда такую окружность провести невозможно (вот пример: О о О ), но такие случаи нас волновать не будут, так как они охватываются пунктом 2.

2. Если даны две окружности, то можно провести много окружностей, касающихся их, но только одна при этом будет охватывать их обе с минимальным радиусом ее центр лежит на отрезке, соединяющем центры.

... Охватывающий круг, будучи уже построен, должен либо а) касаться трех (или больше) кругов из данного набора; либо б) касаться только двух, имея при этом минимальный возможный радиус. Первое довольно очевидно, а во втором убедиться можно, представив себе круг неминимального радиуса, касающийся лишь двух кругов - очевидно, его можно уменьшить.

Итак, алгоритм решения состоит в следующем.
1. Провести полный перебор всех троек кругов. На каждую тройку натягивать касающуся их окружность , после чего перебором по всем оставшимся кругам смотреть, попадают ли они внутрь нее. Из всех таких окружностей ищем окружность с минимальным радиусом. (Для оптимизации вычислений эти две проверки лучше переставить местами: сначала проверять радиус на минимальность - но это лирика).

2. Найти два максимально отстоящие (дальними точками) круга, натянуть на них минимальную окружность и проверить, охватываются ли все остальные круги этой окружностью. Если да, то сравнить с радиусом, полученном в п.1 и выбрать минимальный.

По сути, тут два решения: одно - klem4'овское, только с добавленной проверкой на включение, второе - Бравого Генерала, с тем же самым дополнением.

Все! Казалось бы...

Но действительно ли все? Теоретически - да. А практически..
Выполнить п.2 сложности не представляет - klem4 уже сделал это. А вот п.1.. Хотя ОА принципиально и находима - этого достаточно для математика, для программера этого мало. Надо указать конкретный способ ее найти. Именно это и тормозило меня с самого начала: хотя описанные выше два пункта алгоритма нащупать было несложно, практический способ постороения ОА мне не давался. В указанной ссылке (см. мои предыдущие посты) способ построения геометрический, реализовать его в коде довольно сложно с моей точки зрения. Поэтому я продолжал думать.. Довольно долго все равно все мои усилия были вокруг простой геометрии типа циркулем и линейкой, хотя я понимал, что без инверсии тут не обойтись. В конце концов я на нее решился.

Все оказалось не так уж и страшно smile.gif
Преобразование инверсии, как известно, переводит окружность в окружность, при этом сохраняя касание. Да, конечно - прямо то, что нужно! Только зачем? Зачем переводить окружности в другие? чем другие лучше?

А вот чем. Когда я написал уравнения, оказалось, что возможно провести одну инверсию, которая переведет три заданных окружности в три окружности одного заданного диаметра! Внизу, если останется время, приведу подтвеждающие выкладки.

Итак, общее правило такое:

1. По трем выбранным кругам (центры и радиусы) находим параметры (центр и радиус) того самого преобразования инверсии, которое переводит эти три окружности в три одинаковые.

2. Произвести инверсию.

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

4. Проводим обратную инверсию (то есть вторично применяем ее). Полученный образ построенной в п.3 окружности - это искомая кружность, касающаяся трех данных.

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

Вот теперь, кажется, все.. smile.gif
Ах, да! не все.. Осталось добавить, что, как показывают выкладки, инверсия применяется в трехмерном случае (теперь уже к четырем сферам) вполне аналогично, хотя вычисления усложняются. Далее, в 3D придется рассматривать не два случая, а три:
1. Касание четырех шаров.
2. Минимальное касание трех шаров.
3. Минимальное касание двух шаров.
Строгости ради, сюда (а также выше) надо добавить еще и случай, когда одна из данных сфер уже охватывает все остальные, но он настолько тривиален, что лень было упоминать. Хотя в программном продукте он должен быть учтен, разумеется.

Теперь совесм все!! smile.gif
Ну, как вам решеньеце? Мне почему-то кажется, что с набором из сотни шаров современный Р4 за пару часов справится. smile.gif Но о тысяче не стоит и говорить.. Хотя, простор для оптимизации тут немеряный..

Мужики (дамы так и не присоединились к обсуждению), не судите строго - я выложу вычисления on request - ладно? И так уже больше получаса пишу..

Всем спасибо за внимание! Жду критики (или опровержений smile.gif )


P.S.
Перечитал - и обнаружил в своих рассуждениях ошибку, которая может иметь принципиальное значение. Или, по крайней мере, еще усложнит алгоритм..
Кто еще заметил?
smile.gif


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


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

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

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


Похоже, я изрядно напугал народ своим ответом... smile.gif
Неужели никого не заинтересовало? Все так активно говорили.. Мне кажется, там еще полно материала для обсуждения. Не исключаю, что все же может найтись более простое решение.

И зачинатель темы куда-то делся.. sad.gif
Ау-у!


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

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

 




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