• Добро пожаловать на компьютерный форум Tehnari.ru. Здесь разбираемся с проблемами ПК и ноутбуков: Windows, драйверы, «железо», сборка и апгрейд, софт и безопасность. Форум работает много лет, сейчас он переехал на новый движок, но старые темы и аккаунты мы постарались сохранить максимально аккуратно.

    Форум не связан с магазинами и сервисами – мы ничего не продаём и не даём «рекламу под видом совета». Отвечают обычные участники и модераторы, которые следят за порядком и качеством подсказок.

    Если вы у нас впервые, загляните на страницу о форуме и правила – там коротко описано, как задать вопрос так, чтобы быстро получить ответ. Чтобы создавать темы и писать сообщения, сначала зарегистрируйтесь, а затем войдите под своим логином.

    Не знаете, с чего начать? Создайте тему с описанием проблемы – подскажем и при необходимости перенесём её в подходящий раздел.
    Задать вопрос Новые сообщения Как правильно спросить
    Если пришли по старой ссылке со старого Tehnari.ru – вы на нужном месте, просто продолжайте обсуждение.

Изображение шара в Pascal

Asya_inter

Новые
Регистрация
12 Янв 2015
Сообщения
71
Реакции
0
Баллы
0
Изображение шара в Pascal

Изобразить гладкий красный шар, освещенный Солнцем. Как изобразить куб я знаю, а как шар затрудняюсь. Или нужно просто нарисовать окружность и на ней уже делать тени, блики свет, чтобы он стал объёмным? Подскажите пожалуйста!
 
Pascal это который 7.0 ?
 
Изобразить гладкий красный шар, освещенный Солнцем. Как изобразить куб я знаю, а как шар затрудняюсь. Или нужно просто нарисовать окружность и на ней уже делать тени, блики свет, чтобы он стал объёмным? Подскажите пожалуйста!
Вероятно, что-то в таком роде?
Посмотреть вложение 227282 Посмотреть вложение 227283
Но тут действительно нужно знать, в каком Паскале это требуется. В графических заданиях такая информация обязательна.
 
Ну и в чем проблема? Вы не знаете, как организовать заливку?
Проблема в том, что я не знаю как сделать градацию света и тени, а также изобразить именно ГЛАДКИЙ, а не матовый шар. Если кто-то что-то знает, то поделитесь пожалуйста!
 
а также изобразить именно ГЛАДКИЙ, а не матовый шар.
Увы-увы, у меня получается такой... шероховатый. В общем, надо издали смотреть и без очков - тогда нормально. Вот - в Turbo (Free):
Код:
Uses Graph, CRT;

Var
 R1,X1,Y1,X2,Y2,X,Y:Word;
 Sgm:Real;
 i:LongInt;

Procedure Gs(Sigma:Real; var Xg:Word; var Yg:Word);
var
 u,v,x,y:real;
begin
 u:=Random;
 v:=Random;
 x:=Sqrt(-Ln(v)*2)*Cos(u*2*Pi)*Sigma;
 y:=Sqrt(-Ln(v)*2)*Sin(u*2*Pi)*Sigma;
 if Sqrt(Sqr(X2+x-1.0*X1)+Sqr(1.0*Y2-y-Y1))>R1 then
  begin
   Xg:=X2;
   Yg:=Y2;
  end
 else
  begin
   Xg:=Round(1.0*X2+x);
   Yg:=Round(1.0*Y2-y);
  end;
end;

Begin
 InitGraph(...  { [COLOR=Red][B]Тут - самостоятельно![/B][/COLOR] }
 Randomize;
 SetBkColor(7);
 R1:=GetMaxY div 4;
 X1:=GetMaxX div 2;
 Y1:=GetMaxY div 2;
 SetColor(8);
 SetFillStyle(SolidFill,8);
 FillEllipse(X1,Y1,R1,R1);
 X2:=Round(X1+0.3*R1);
 Y2:=Round(Y1-0.3*R1);
 Sgm:=R1/3;  {Red}
 for i:=1 to 400000 do
  begin
   Gs(Sgm,X,Y);
   PutPixel(X,Y,4);
  end;
 Sgm:=R1/4;  {LightRed}
 for i:=1 to 80000 do
  begin
   Gs(Sgm,X,Y);
   PutPixel(X,Y,12);
  end;
 Sgm:=R1/5;  {Yellow}
 for i:=1 to 10000 do
  begin
   Gs(Sgm,X,Y);
   PutPixel(X,Y,14);
  end;
 ReadKey;
 CloseGraph;
End.
 

Вложения

  • FP01.webp
    FP01.webp
    18.8 KB · Просмотры: 116
Vladimir_S, я знаю, что нужно использовать формулу расчета видимости яркости гладкой поверхности с учетом зеркального отражения(она на фото). Но как её применить я не знаю...Может вы знаете?ббб.webp
 
Vladimir_S, я знаю, что нужно использовать формулу расчета видимости яркости гладкой поверхности с учетом зеркального отражения(она на фото). Но как её применить я не знаю...Может вы знаете?
Догадываюсь... Вообще-то с этого (с выкладывания формул) и нужно было начинать. Но это - ой, сколько работы... Между прочим, всё равно поверхность шара получится, как и у меня - такой... ноздреватой. Потому что я не вижу иных средств сымитировать переменную яркость, кроме как густотой точек.
Ладно, раз примененное мною гауссово распределение не годится, попробую с косинусным.
P.S. Мгновенно не обещаю.
P.P.S. Но задачка - интересная.
 
Vladimir_S, буду очень рада, если подскажите! Получается, нельзя сделать плавного перехода в цвете?
 
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. Процедуру повторяем М раз.

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

Дерзайте!
 
Где-то на месячишку плотной работы.
Это значит, что более простого способа решения этой задачи нет? Спасибо! Буду разбираться (мне это нужно сделать за неделю) Если, что-то получится, то отправлю сюда.
 
Мне помогли с решением. Но оно другое и на 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.
 
Назад
Сверху