Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];

Вниз

Сфера случайных точек   Найти похожие ветки 

 
Still_Swamp ©   (2003-08-09 18:05) [0]

Кто может предложить алгоритм заполнения поверхности сферы радиусом R случайными точками с координатами x,y,z?

Координаты собстно и надо найти.


 
NDeu ©   (2003-08-09 19:58) [1]

X:=R*COS(Random);
Y:=R*COS(Random);
Z:=R*COS(Random);


 
NDeu ©   (2003-08-09 20:00) [2]

Точнее:
X:=R*Random;
Y:=R*Random;
Z:=R*Random;




 
TButton ©   (2003-08-09 21:00) [3]

w:=random(2PI);
q:=random(2PI);
x:=COS(w)*SIN(q)*r;
y:=COS(w)*COS(q)*r;
z:=SIN(w);
imho так должно быть


 
Still_Swamp ©   (2003-08-10 12:18) [4]

Да нет уж - извиняюсь... я хотел случайное распределение. А это изделие на полюсах сферы организует повышенную плотность точек. Могу даже пояснить почему...

у тебя ar - это радиус круга во второй плоскости, для которой ты генеришь случайный угол. но к сожалению, окружность у этого круга - тем меньше, чем ближе ты подбурешся к PI/2, а вот количество точек к сожалению не меньше.

есть еще идеи?


 
TButton ©   (2003-08-10 22:08) [5]

логично... дай по думать...
вписываем сферу в куб, расстояние от центра сферы до угла куба = SQRT(r^2+r^2+r^2), расстояние от центра сферы до точки на ее поверхности = r...
можно попробовать так (обозночаем растояние до угла как rfar):
x:=random*(r/rfar);
z:=random*(r/rfar);
y:=random*(r/rfar);

или что-то в етом роде... вобщем, если генерить просто случайные координаты (в пределах радиуса), то они заполнят куб а не сферу...


 
NailMan ©   (2003-08-11 11:58) [6]

Вот мой генератор звездного неба, распределяющий вершины буфера по сферической поверхности заданного радиуса:

Procedure TGameResourceManager.GenerateStarField(Const Count:cardinal;const Radius:Single; Var pb:PByte;Const Seed:Cardinal);
 Var
     nulp : Pointer;
     Vert : PSF_Vertex;
        i : DWORD;
   thetaC,
     PhiC,
     kall,
    Kall2 : Single;
    a,b,c : Byte;
begin
  nulp:=pb;
  vert:=nulp;
  RandSeed:=Seed;
   For i:=0 to Count-1 do begin
    ThetaC:=Random(90);
    PhiC:=Random(360);
    Kall:=Random(180);
    Kall2:=Random(90);
    ThetaC:=ThetaC * pi /180;
    PhiC:=PhiC * pi /180;
    Kall:=Kall * pi /180;
    Kall2:=Kall2 * pi /180;
    a:=random(2);b:=random(2);c:=random(2);
    if a=0 then ThetaC:=-ThetaC;
    if (b=0) and (ThetaC>0) then ThetaC:=ThetaC-Kall2;
    if (b=1) and (ThetaC<0) then ThetaC:=ThetaC+Kall2;
    if c=0 then PhiC:=PhiC+Kall else PhiC:=PhiC-Kall;
   vert^.XYZ.X:=Radius * Cos(ThetaC) * Cos(PhiC);
   vert^.XYZ.Y:=Radius * Sin(ThetaC);
   vert^.XYZ.Z:=Radius * Cos(ThetaC) * Sin(PhiC);
   repeat
    A:=Random(256);
   until a in[128..255];
   Vert^.Color:=d3dcolor_xrgb(a,a,a);
   inc(vert);
                          end;
end;

Не спрашивайте почему это написанно так - давно писал, лень переделывать по культурному. Возможно переделаю с Random на RandG и чё-нить покрасивше чтоб было.


 
Alek Aaz ©   (2003-08-12 06:17) [7]

Ну вы даете ...

alfa:= random(360);
beta:=random(180);
x:=cos(alfa/180*Pi);
y:=sin(alfa/180*Pi);
z:=sin(beta/180*Pi);

Вы чо? Прикалываетесь?


 
Alek Aaz ©   (2003-08-12 07:55) [8]

Ну я даю ...

alfa:= random(360);
beta:=random(180)-90;
x:=R*cos(alfa/180*Pi)*sin(beta/180*Pi);
y:=R*sin(alfa/180*Pi)*sin(beta/180*Pi);
z:=R*cos(beta/180*Pi);

Вообще, содрал от сюда http://delphigfx.mastak.ru/2d/009/2d_9.htm


 
TButton ©   (2003-08-12 15:34) [9]

2 Alek Aaz

TButton ©   (09.08.03 21:00) [3]
w:=random(2PI);
q:=random(2PI);
x:=COS(w)*SIN(q)*r;
y:=COS(w)*COS(q)*r;
z:=SIN(w);
imho так должно быть

в одном с тобой согласен q:=rand(pi)-pi/2


 
wiz ©   (2003-08-13 01:40) [10]

Вот что пришло в голову (идея алгоритма):

Шаг 1: Заполняем случайными точками куб (-2..2;-2..2;-2..2). Т.к. при заполнении используем равномерное по каждой координате распределение (что-то вроде random*4-2), то плотность точек во всем кубе - одинакова (в пределе ;) ).

Шаг 2: Отбрасываем все точки расстояние от центра до которых больше 2 или меньше 0.5. Получили толстостенную сферу, равномерно заполненную точками.

Шаг 3: Отображаем все точки на нужную сферу (радиуса 1). Т.е. нормируем все радиус-векторы точек (xi,yi,zi):

Ri = sqrt(xi^2 + yi^2 + zi^2);
xi" = xi/Ri;
yi" = yi/Ri;
zi" = zi/Ri;


Множество точек (xi",yi",zi") и будет искомым заполнением.

Вопросы:

В1: Почему распределение на сфере будет равномерным?
1) Т.к. фигура после "шага 2" - центрально-симметричная, то легко показать, что в любые два одинаковых телесных угла попадает одинаковое количество точек (опять же в пределе).
2) При отображении одинаковых телесных углов на сферу, площади отображения равны (очевидно, но строго доказать не помню как).
3) из (1) и (2) получается, что на любые две одинаковые площадки приходится одинаковое кол-во точек (что и требовалось).

В2: Почему в "шаге 2" я откидываю точки в шарике 0.5?
Судя по теории можно и не откидывать, но мне почему-то кажется, что из-за близости к центру (и соответственно большей неопределенности по направлению) могут возникать перекосы и сильные отклонения от равномерного распределения в случае небольшого кол-ва точек.

В3 (К самому себе и знатокам): Является ли написаное выше правдой или я где-то все-же ошибся?


 
wiz ©   (2003-08-13 12:19) [11]

На свежую голову написал програмку на этом алгоритме: все сухо, распределение равномерное на глаз (честно считать ломы). Так что можете пользоваться.


 
wiz ©   (2003-08-17 15:06) [12]

А спасибо???


 
MeF88 ©   (2003-08-25 18:26) [13]

А почему у меня форум глючит?
P.S. Модераторам и Админам плиз удалите это, так как может после этого сообщения текущие темы у меня обновляться.


 
Eugen   (2003-09-06 19:43) [14]

Абсолютно правильное замечание от Still_Swamp о создании повышенной плотности на полюсах. Алгоритм от wiz выглядит слишком сложным.

Возможным решением является следующее.

Выбираем случайный вектор в трехмерном пространстве:
(r1,r2,r3), где r1,r2,r3-случайные величины.
Здесь нужно сделать проверку, что наш вектор не нулевой, дабы наш алгоритм работал в 100% случаев.

Пишем параметрическое уравнение прямой проходящей через центр сферы в направлении (r1,r2,r3). В случае, если центр сферы в нуле, уравнение прямой выглядит следующим образом:
r=(r1,r2,r3)t, где t-параметр.

Ищем точки пересечения этой прямой со сферой:
(r1t)^2+(r2t)^2+(r3t)^2=R^2, где R- радиус сферы.
Имеем квадратное уравнение
(r1^2+r2^2+r3^2)t^2=R^2

Оно имеет два решения, из которого нам интересно только одно, скажем
t=R/sqrt(r1^2+r2^2+r3^2)

Осталось насадить на сфере нашу случайную точку:
x=r1*t=r1*R/sqrt(r1^2+r2^2+r3^2)
y=r2*t=r2*R/sqrt(r1^2+r2^2+r3^2)
z=r3*t=r3*R/sqrt(r1^2+r2^2+r3^2)

Программа (на C) выглядит примерно следующим образом:
float x,y,z;
float r1,r2,r3;

float R=100;

r1=rnd(); r2=rnd(); r3=rnd();
float d=sqrt(r1*r1+r2*r2+r3*r3);

x=R*r1/d;
y=R*r2/d;
z=R*r3/d;

//(x,y,z) - координаты точки на сфере


 
TButton ©   (2003-09-06 19:48) [15]

странная прога. во-первых rnd дает 0..1 => заполнится тока 1/8 сферы, а во вторых - совсем не обязательно что точка будет лежать на поверхности сферы

з,Ы.
 Не тот ли это Евген, который пал? ;)


 
Всеволод Соловьёв ©   (2003-09-06 22:05) [16]

Я могу написать норм. распределние именно по поверхности сферы.


 
NailMan ©   (2003-09-08 14:51) [17]

Ну я наконец-то появился в тырнете и хочу сказать что успешно реализовал заполнение звездной сферы через куб.
Делал тупо и стабильно - набил куб произвольного размера(я делал со стороной 100) 4000 точками с неким рандомным цветом(оттенки серого) [128..255]. Далее просто нормализовал каждую точку.

Получилось вполне пристойно по всей поверхности. Много визуально двойных звезд получилось, что не получалось, когда я по сферич. координатам распределял.

Вобщем если кому не жалко траффика на 880Кб, то можете скачать мою демку GUI-интерфейса, где на бэкграунде эти звезды и вращаются. Заодно и оцените сам интерфейс.


 
pasha_676 ©   (2003-09-08 15:32) [18]

Случайный угол с одной плоскости через random случайный угол в другой плоскости. Далее что нам известно - углы, центр сферы и радиус сферы. Надо найти координаты этой точки. (почти по варианту TButton-a - у него ошибка в явном виде на определение координаты Z)

Не замарачиваясь сейчас на трехмерку. В двухмерном пространстве это будет
x:=cos(A)*R
y:=sin(A)*R

Распределение будет вполне равномерным.

В трехмерном добавиться еще одна координата и еще один угол. Но ведь это по идеи ни на что не должно влият?

Вопрос собственно а почему это будет неравномерно?
Мне кажется будет равномерно... Кажется и вроде бы... Вы меня заинтересовали. Сейчас на работе разгребусь и попробую сделать модельку. Посмотрю что выйдет.


 
NailMan ©   (2003-09-08 15:57) [19]

У полюсов получаются кольцевые уплотнения, хотя я их немного сглаживал вводя дополнительную рандомную величину которая рандомно прибавлялась или вычиталась от углов.

Но все таки это также было попсово - полюса все равно просматривались. Кубическим заполнением с последющей нормализацией получилось намного правдоподобней и красивше.

Тем более с кубом можно играться - следать реальное уплотнение звезд (вернее его проекцию) аля Млечный путь, скопления(любые).

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


 
pasha_676 ©   (2003-09-09 09:23) [20]

А почему у полюсов плющется? По идеи не должно. Ладно - будет время проверю. Интересно стало


 
Рамиль ©   (2003-09-10 16:36) [21]


> Делаешь это в реальном пространстве, а потом проецируешь(нормализуешь)
> и все выглядит естесственно как будто ты действительно смотришь
> на скопление звезд.

Так тогда лучше забивать точками сферу, а потом проецировать.


 
NailMan ©   (2003-09-10 17:34) [22]

Рамиль ©
Ну и как(каким алгоритмом) ты собираешься забивать именно сферу? Тут формула геморройная будет, а вот конкретный код генерации звезд по кубу:

type
TSF_Vertex = packed record
XYZ : TD3DVector; //12
Color : TD3DColor;  //4
End;
PSF_Vertex = ^TSF_Vertex;

Procedure StarFieldGenerator(var pb:pbyte;count:integer);
 Var
     Vert : PSF_Vertex;
        i : DWORD;
        a : Byte;
begin
randomize;  
  vert:=pointer(pb);
//Создаем кубический звездный объем
   For i:=0 to Count-1 do
    begin
     Vert^.XYZ.x:=RandG(0,100);
     Vert^.XYZ.y:=RandG(0,100);
     Vert^.XYZ.z:=RandG(0,100);
     inc(vert);
    end;

  vert:=pointer(pb);
   For i:=0 to Count-1 do
    begin
     repeat
      a:=Random(256);
     until a in[128..255];
     Vert^.Color:=d3dcolor_xrgb(a,a,a);
      Vert^.XYZ:=VectorNormalize(Vert^.XYZ);
     inc(vert);
    end;
end;


Проще паренной репы. Какая собсно разница в каком объеме набивать звезды - куб проще всего.



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.026 c
1-1079632695
Chcnger
2004-03-18 20:58
2004.04.04
Числа


1-1079185034
Kor@l
2004-03-13 16:37
2004.04.04
Rave


3-1078121878
jenya_d
2004-03-01 09:17
2004.04.04
Компонент для закачки/обновления данных между таблицами IB


3-1078677156
VitGun
2004-03-07 19:32
2004.04.04
Хранение докуметов Word в базе данных Access


3-1078501438
klyonov
2004-03-05 18:43
2004.04.04
TDBGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский