Технический форум
Вернуться   Технический форум > Программирование > Форум программистов > Помощь студентам


Ответ
 
Опции темы Опции просмотра
Старый 31.05.2015, 11:10   #11 (permalink)
Vladimir_S
Специалист
 
Регистрация: 27.08.2008
Адрес: Санкт-Петербург
Сообщений: 27,807
Сказал(а) спасибо: 340
Поблагодарили 583 раз(а) в 208 сообщениях
Репутация: 113184
По умолчанию

Цитата:
Сообщение от Asya_inter Посмотреть сообщение
Vladimir_S, буду очень рада, если подскажите! Получается, нельзя сделать плавного перехода в цвете?
Ася!
1. Насчет плавного перехода - по-моему, таких сервисов в Паскале не предусмотрено. Только густотой точек. Впрочем, если у Вас есть графпакет, который может работать с экраном высокого разрешения, то это оно и будет. У меня только VGA-мода (640х480).

2. По самой задаче.
Начнем с рассеянного света.
Как я вижу, задача решается так.

а) Рисуем темный (фоновый) круг.

б) Вводим две системы сферических координат. Первая (основная) решает задачу, когда солнце светит в направлении "северного полюса", т.е. вдоль оси Z, т.е. θ=0, φ - произвольное. Вторая (повернутая) - для случая, когда солнце светит в направлении θs, φs. Ищем в книжках, на сайтах либо, мобилизуя все знания матричной алгебры, решаем самостоятельно задачу перехода от основной к повернутой системе координат, т.е. задачу преобразования координат
θ, φ → θ', φ' для любой точки сферы.

в) Методом случайного выбора задаем угол θ в основной системе координат. Фишка в том, что распределение здесь не равномерное, а косинусное. Подскажу, что оно задается функцией θ = arcsin(x), где х - равномерно распределенная случайная величина в интервале 0-1, т.е. значение функции Random без параметров. Также методом случайного выбора задаем φ=Random*2π. На всякий случай, приведу вид функции вычисления арксинуса:
Код:
function ArcSin(X:Real):Real;
begin
  if X= 1 then ArcSin:= Pi/2 else
  if X=-1 then ArcSin:=-Pi/2 else
  ArcSin:=ArcTan(X/Sqrt(1-X*X));
end;
г) Делаем переход от θ, φ к θ', φ'.

д) В повернутой системе определяем декартовы координаты Y' и Z' (плоскость рисунка) нашей точки.

е) В случае выполнения условия (Y')²+(Z')²≤R² ставим красную точку с координатами Y' (по горизонтали) и Z' (по вертикали).

ж) Повторяем процедуру, пока не станет красиво. Или до потери пульса.

Итак, будем считать, что с рассеянным светом разобрались. Но это всё как раз еще цветочки. Ягодки начнутся, когда мы захотим решить задачу зеркального отражения. Вот тут - совсем ой! Здесь я вижу решение, например, такое:

а) Фоном является решение предыдущей задачи.

б) Переходим в основную систему координат (солнце светит в направлении Z=0). Задаем в этой системе направление на наблюдателя θн, φн. Забегая вперед, отмечу, что, когда мы повернем систему, это направление изменится - ну да нам-то не всё ли равно?

в) Разбиваем верхнюю полусферу на элементы площадью S=R²sin(θ)ΔθΔφ. В двойном цикле проходим их все.

г) Для каждого элемента определяем угловые координаты луча, соответствующего отражению, исходя из постулата "угол падения равен углу отражения". Эти координаты составят θr=2θ, φr=φ.

д) Определяем угол β между направлением отраженного луча и направлением на наблюдателя (в трехмерном пространстве, не забываем!).

е) Заполняем случайным образом элемент поверхности S так:
i. Фиксируем полное количество "квантов" N, упавших на каждый элемент поверхности площадью S (для всех элементов это число будет одинаковым). Например, N=1000. Или 10000. Или еще сколько-нибудь. Тогда число точек М для каждого из элементов определится из соотношения M=Round(N(cos²β)²) (в смысле косинуса в четвертой степени).
ii. Выбираем для каждой точки углы θр, φр так:
θp = θ + Δθ(0.5-Random)
φp = φ + Δφ(0.5-Random)
iii. Как и в предыдущей задаче, для каждой точки переходим к повернутой системе координат и, как и в том случае, при выполнении условия в пункте е) ставим желтую точку.
iiii. Процедуру повторяем М раз.

Вот как-то так. Такой вот конгломерат из векторной алгебры, аналитической геометрии, оптики, дизайна и программирования. Где-то на месячишку плотной работы.

Дерзайте!
Vladimir_S вне форума   Ответить с цитированием

Старый 31.05.2015, 11:10
Helpmaster
Member
 
Аватар для Helpmaster
 
Регистрация: 08.03.2016
Сообщений: 0

Некоторые темы по содержанию очень напоминают вашу тему

Погрешности для вычисления объема шара. Численные методы
Создание развертки шара
Изображение пропадает

Старый 01.06.2015, 01:12   #12 (permalink)
Asya_inter
Member
 
Аватар для Asya_inter
 
Регистрация: 12.01.2015
Сообщений: 71
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию

Цитата:
Сообщение от Vladimir_S Посмотреть сообщение
Где-то на месячишку плотной работы.
Это значит, что более простого способа решения этой задачи нет? Спасибо! Буду разбираться (мне это нужно сделать за неделю) Если, что-то получится, то отправлю сюда.
Asya_inter вне форума   Ответить с цитированием
Старый 01.06.2015, 09:38   #13 (permalink)
Vladimir_S
Специалист
 
Регистрация: 27.08.2008
Адрес: Санкт-Петербург
Сообщений: 27,807
Сказал(а) спасибо: 340
Поблагодарили 583 раз(а) в 208 сообщениях
Репутация: 113184
По умолчанию

Цитата:
Сообщение от Asya_inter Посмотреть сообщение
Это значит, что более простого способа решения этой задачи нет?
Да откуда ж мне знать? Может, и есть. Просто я увидел именно такой способ.
Vladimir_S вне форума   Ответить с цитированием
Старый 13.06.2015, 00:34   #14 (permalink)
Asya_inter
Member
 
Аватар для Asya_inter
 
Регистрация: 12.01.2015
Сообщений: 71
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию

Мне помогли с решением. Но оно другое и на PascalABC. Но я не совсем понимаю как здесь использована формула. И вообще как идет затемнение, осветление. Может кто знает, подскажите пожалуйста! Просто очень нужно и интересно. Хочу также с кубом сделать.

Код:
program zadacha_4;
uses
   GraphABC;

const
   {window center}
   xc = 300;
   yc = 250;
   {ball}
   xb = 100;
   yb = 10;
   zb = 70;
   R = 70;
   {vector sun}
   sx = -30;
   sy = -2;
   sz = -11;

type
   tPoint = record
      x, y, z: real;
   end;


procedure DrawPixel(x, y: real; R, G, B: integer);
begin
   if R < 0 then R := 0;
   if G < 0 then G := 0;
   if (B < 0) then B := 0;
   if (x > 0) and (y > 0) then 
      SetPixel(round(x), round(y), RGB(R, G, B));
end;


function Angle(sx, sy, sz, x, y, z: real): real;
var
   A: real;
begin
   A := 0;
   if sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z))) <> 0 then
      A := (sx * (xb - x) + sy * (yb - y) + sz * (zb - z)) / sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z)));
   Angle := A;
end;

function ForeAngle(sx, sy, sz, x, y, z: real): real;
var
   A: real;
begin
   A := 0;
   if sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z))) <> 0 then
      A := (sx * (xb - x) + sy * (yb - y) + sz * (zb - z)) / sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z)));
   if A > 0 then
      ForeAngle := A * A * A * A
   else 
      ForeAngle := -A * A * A * A;
end;

var
   i, j, k: integer;
   shadow: tPoint;

begin
   SetWindowSize(2 * xc, 2 * yc);
   SetBrushColor(clBlack);
   SetPenColor(clBlack);
   Window.Clear(rgb(200, 200, 200));
   LockDrawing;
   for i := xb - R + 1 to xb + R - 1 do 
      for j := round(yb - sqrt(R * R - (i - xb) * (i - xb))) + 1 to round(yb + sqrt(R * R - (i - xb) * (i - xb))) - 1 do
         for k := round(zb - sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) to round(zb + sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) do
         begin
            
               {sun}
            if sz < 0 then begin
               shadow.x := (i - (i - sx)) / (1 - k / (k - sz)) + i - sx;
               shadow.y := (j - (j - sy)) / (1 - k / (k - sz)) + j - sy; 
            end;
               {point}
               {shadow.x :=(i-xl)/(1-k/zl)+xl;
               shadow.y :=(j-yl)/(1-k/zl)+yl; }
            
               {DrawPixel(round(shadow.x)+xc,round(shadow.y)+yc,55,55,55);}
            DrawPixel(round(-(sqrt(3 / 4) * (-shadow.y + shadow.x)) / 1.2 + xc), round(-(0 - (shadow.x + shadow.y) / 2) / 1.2 + yc), 55, 55, 55);
         end;      
   
   for i := xb - R + 1 to xb + R - 1 do 
      for j := round(yb - sqrt(R * R - (i - xb) * (i - xb))) + 1 to round(yb + sqrt(R * R - (i - xb) * (i - xb))) - 1 do
         for k := round(zb - sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) to round(zb + sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) do
         begin
               {DrawPixel(i+xc,j+yc,255,0,0);}
            DrawPixel(round(-(sqrt(3 / 4) * (-j + i)) / 1.2 + xc), round(-(k - (i + j) / 2) / 1.2 + yc), round(95 + 100 * Angle(sx, sy, sz, i, j, k) + 60 * ForeAngle(sx, sy, sz, i, j, k)), round(290 * ForeAngle(sx, sy, sz, i, j, k) - 55), round(290 * ForeAngle(sx, sy, sz, i, j, k) - 55));
         end; 
   
   Redraw;
end.
Asya_inter вне форума   Ответить с цитированием
Ads

Яндекс

Member
 
Регистрация: 31.10.2006
Сообщений: 40200
Записей в дневнике: 0
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 55070
Ответ

Метки
pascal, задача, помощь


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.




Часовой пояс GMT +4, время: 07:39.

Powered by vBulletin® Version 6.2.5.
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.