Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.04;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.024 c
11-1058382320
puky
2003-07-16 23:05
2004.04.04
Bitmap.PasteFromClipboard


4-1072734449
Volkov
2003-12-30 00:47
2004.04.04
Как сменить имя процесса?


14-1078769139
Patriarch
2004-03-08 21:05
2004.04.04
Смайлики


3-1078328414
В л а д и м и р
2004-03-03 18:40
2004.04.04
Экспорт данных из таблицы Exel в таблицу базы данных


4-1074922175
Lefan
2004-01-24 08:29
2004.04.04
Перехват кликов мыши....