program Globe;
uses
	Graph;
const
	r    = 50; 			  {Радиус сферы}
   A    = 0;  			  {Коэффициенты общего уравнения плоскости}
   B    = 0;
   C    = 1;
   D    = 50;
   sx   = 50; 		  	  {Координаты источника света}
   sy   = 0;
   sz   = 100;
   kp   = 10;   		  {Коэффициенты поверхности}
   kn   = 0.5;
   Ip   = 10;
   Ina  = 50;
   k1   = kp*Ip;
   k2   = kn*Ina;
   step = 0.017453293; {Шаг изменения угла(один градус)}
type
	tPoint = record  {Точка}
   	x, y, z: real
   end;
   tLine = record   {Отрезок}
   	bol, eol: tPoint
   end;
   tPlane = record  {Плоскость}
   	A, B, C, D: real
   end;
   tVector = record {Вектор}
   	x, y, z: real
   end;
   tSpot = record   {Источник света (точечный)}
   	x, y, z: integer
   end;
var
	Gd, Gm 	 : integer; {Графика}
   normal	 : tVector; {Вектор нормали к поверхности сферы}
   light		 : tVector; {Вектор луча света}
   p1, p2	 : tPoint;  {Точки}
   pInt		 : tPoint;  {Точка пересечения}
   plane		 : tPlane;  {Поверхность}
   spot		 : tSpot;   {Источник света}
   lin		 : tLine;   {Прямая}
   I		    : byte;    {Яркость поверхности}
   alfa, beta: real;    {Углы}

procedure Proection(var p: tPoint); {Кабинентная проекция}
begin
	p.x:= GetMaxX div 2 + p.x + p.y/(4*sqrt(2));
   p.y:= GetMaxY div 2 - p.z + p.y/(4*sqrt(2));
end;

procedure DrawAxes(c: integer); {Рисование осей}
const
	indent = 10;
begin
   SetColor(c);
   Line(GetMaxX div 2, GetMaxY div 2, GetMaxX, GetMaxY div 2); {X}
   OutTextXY(GetMaxX - indent, GetMaxY div 2 + indent, 'X');
   Line(GetMaxX div 2, GetMaxY div 2, 0, GetMaxY); 				{Y}
   OutTextXY(0, GetMaxY - 2*indent, 'Y');
   Line(GetMaxX div 2, GetMaxY div 2, GetMaxX div 2, 0); 		{Z}
   OutTextXY(GetMaxX div 2 +indent, indent, 'Z');
end;

procedure Interception(l: tLine; s: tPlane); {Исследование взаимного}
var                                          {		 положения       }
	p: tVector;                               {  прямой и плоскости  }
   M, N, t: real;
begin
   p.x:= l.bol.x - l.eol.x;
   p.y:= l.bol.y - l.eol.y;
   p.z:= l.bol.z - l.eol.z;
   M:= s.A*p.x + s.B*p.y + s.C*p.z;
   N:= s.A*l.bol.x + s.B*l.bol.y + s.C*l.bol.z + s.D;
   if M <> 0 then begin
   	t:= -(N)/M;
		pInt.x:= l.bol.x + p.x*t;
		pInt.y:= l.bol.y + p.y*t;
      pInt.z:= l.bol.z + p.z*t;
	end;
end;

function Cosinus(p: tPoint): real; {Косинус угла между векторами}
var
	b: tVector;
begin
   b.x:= abs(p.x - sx);
   b.y:= abs(p.y - sy);
   b.z:= abs(p.z - sz);
	Cosinus:= (p.x*b.x + p.y*b.y + p.z*b.z)/
  	(Sqrt(Sqr(p.x) + Sqr(p.y) + Sqr(p.z))*Sqrt(Sqr(b.x) + Sqr(b.y) + Sqr(b.z)));
end;

begin
   {Инициализация графики}
	   Gd:= Detect;
	   InitGraph(Gd, Gm, 'C:\BP\BGI'); { Путь к BGI драйверам }
	   if GraphResult <> grOk then
			Halt;
   {Рисование}
      SetBkColor(3);
      plane.A:= A;
      plane.B:= B;
      plane.C:= C;
      plane.D:= D;
      lin.bol.x:= sx;
      lin.bol.y:= sy;
      lin.bol.z:= sz;
      alfa:= 0;
      while alfa <= pi do begin
      	beta:= 0;
         while beta < 2*pi do begin
         	p1.x:= r*Sin(alfa)*Cos(beta);
            p1.y:= r*Sin(alfa)*Sin(beta);
            p1.z:= r*Cos(alfa);
            lin.eol:= p1;
            Proection(p1);
            Interception(lin, plane);
		      I:= Round(k1 + k2*Cosinus(p1));
      		PutPixel(Trunc(p1.x), Trunc(p1.y), I); 	 {Точки сферы}
      		Proection(pInt);
      		PutPixel(Round(pInt.x), Round(pInt.y), 8); {Тень сферы}
            beta:= beta + step;
         end;
         alfa:= alfa + step;
      end;
      SetColor(yellow);
      Proection(lin.bol);
      SetFillStyle(SolidFill, yellow);
      FillEllipse(round(lin.bol.x), round(lin.bol.y), 3, 3);
	ReadLn;
	CloseGraph;
end.