2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 График функции комплексного переменного.
Сообщение07.10.2023, 10:16 
Пытаюсь освоить функции комплексного переменного и мне не хватает геометрической или физической наглядности.

Но трёхмерного пространства не хватает: аргумент - плоскость (2D), область значения - тоже требует плоскости (2D) итого нужно 4-хмерное пространство, в котором мыслить ой-ой.

В каких программах или какими средствами вы строите графики ФКП?
Где посмотреть образцы красивых графиков наиболее часто встречающихся функций?
Есть ли вообще смысл строить такие графики?
Существуют ли какие-либо стандарты на графическое изображение ФКП?

 
 
 
 Re: График функции комплексного переменного.
Сообщение07.10.2023, 11:37 
Можно строить отдельно вещественную и мнимую часть.
Можно вот так.
А вообще комплексны функции традиционно понимаются как преобразования плоскости. Соответственно, визуализируются в виде искажения исходной координатной сетки или векторного поля.
Вот в этом ролике неплохо показаны некоторые способы https://www.youtube.com/watch?v=NtoIXhUgqSk

 
 
 
 Re: График функции комплексного переменного.
Сообщение07.10.2023, 11:47 
Спасибо огромное.
MathCad 14 позволяет отобразить векторное поле. В каких программах делаются другие визуализации?

 
 
 
 Re: График функции комплексного переменного.
Сообщение20.08.2025, 11:41 
Ну вот например по вдохновению ссылкой Dedekinda за час на Delphi была сделана такая визуализация https://youtu.be/btfPS1CXiA0
Исходники:
Код:
// в "Вероятности на алгебрах 1965" на стр.24 упомянута "хорошо известная"
// группа преобразований, образованная дробно-линеынйми функциями
//                        (z1+z)/(1+сопряж(z1)*z)
// для визуализации этого преобразования и созданно данное приложение
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.Imaging.jpeg,
  Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    ImageIn: TImage;
    ImageOut: TImage;
    Panel1: TPanel;
    StaticText1: TStaticText;
    Button1: TButton;
    PaintBox1: TPaintBox;
    Timer1: TTimer;
    Image1: TImage;
    PaintBox2: TPaintBox;
    Image2: TImage;
    procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Panel1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Transformation(za,zb:extended;var newX,newY:extended);
    procedure Retransformation(za,zb:extended;var newX,newY:extended);
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormClick(Sender: TObject);
  private
    { Private declarations }
    z1a,z1b:extended;
    Bitmap1,Bitmap2:TBitmap;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  W = 640; // ширина PaintBox
  H = 512; // высота PaintBox
var
  // массив пикселей (можно динамический, но там чуть сложнее)
  Bits1: array[0..H-1,0..W-1] of TColor;
  BitsInfo1: BITMAPINFO;
  Bits2: array[0..H-1,0..W-1] of TColor;
  BitsInfo2: BITMAPINFO;
// отрисовка массива на устройство DC:
function DrawToDC1(DC: HDC; X, Y, Width, Height: Integer): Integer;
begin
  with BitsInfo1.bmiHeader do
  begin
    biWidth := Width;
    biHeight := -Height;
  end;
  Result := SetDIBitsToDevice(
    DC,
    X, Y, Width, Height,
    0, 0, 0, Height,
    @Bits1, BitsInfo1, DIB_RGB_Colors
  );
end;
// рисуем точку
procedure Plot1(x,y: Integer; C: TColor);
begin
  if (x>=0) and (y>=0) and (x<W) and (y<H) then begin
    Bits1[y,x] := C;
  end;
end;
// отрисовка массива на устройство DC:
function DrawToDC2(DC: HDC; X, Y, Width, Height: Integer): Integer;
begin
  with BitsInfo2.bmiHeader do
  begin
    biWidth := Width;
    biHeight := -Height;
  end;
  Result := SetDIBitsToDevice(
    DC,
    X, Y, Width, Height,
    0, 0, 0, Height,
    @Bits2, BitsInfo2, DIB_RGB_Colors
  );
end;
// рисуем точку
procedure Plot2(x,y: Integer; C: TColor);
begin
  if (x>=0) and (y>=0) and (x<W) and (y<H) then begin
    Bits2[y,x] := C;
  end;
end;

var first:boolean=true;

procedure TForm1.Retransformation(za,zb:extended;var newX,newY:extended);
var upA,upB,downA,downB,norma:extended;
begin
upA:=za-z1a;
upB:=zb-z1b;
downA:=1-(z1a*za+z1b*zb);
downB:=-(z1a*zb-z1b*za);
norma:=downA*downA+downB*downB;
if norma=0 then
  begin
   if (upA*downA+upB*downB)=0 then newX:=1 else newX:=0;
   if (upB*downA-upA*downB)=0 then newY:=1 else newY:=0;
  end else
  begin
   newX:=(upA*downA+upB*downB)/norma;
   newY:=(upB*downA-upA*downB)/norma;
  end;
end;

function getRGB(oldX,oldY:extended;mode:byte):TColor;
var modul,arg:extended;
  re,ge,be:extended;
  r,g,b:byte;
begin
      modul:=sqrt(oldX*oldX+oldY*oldY);
    if modul=0 then modul:=0.000000000000001;
    if (oldX=0)and(oldY=0) then arg:=0 else;
    if (oldX>0)and(oldY=0) then arg:=0 else
    if (oldX>0)and(oldY>0) then arg:=ArcTan(oldY/oldX) else
    if (oldX=0)and(oldY>0) then arg:=pi/2 else
    if (oldX<0)and(oldY>0) then arg:=pi-ArcTan(-oldY/oldX) else
    if (oldX<0)and(oldY=0) then arg:=pi else
    if (oldX<0)and(oldY<0) then arg:=pi+ArcTan(oldY/oldX) else
    if (oldX=0)and(oldY<0) then arg:=pi+pi/2 else
    if (oldX>0)and(oldY<0) then arg:=2*pi-ArcTan(-oldY/oldX);
     re:=55*ln(1+(modul/1412)*255*2*abs(0.5-(arg-0)/(2*pi)));
     ge:=55*ln(1+(modul/1412)*255*2*abs(0.5-abs(arg-2*pi/3)/(2*pi)));
     be:=55*ln(1+(modul/1412)*255*2*abs(0.5-abs(arg-2*2*pi/3)/(2*pi)));
    if re>255 then re:=255;
    if ge>255 then ge:=255;
    if be>255 then be:=255;
    r:=round(int(re));
    g:=round(int(ge));
    b:=round(int(be));
    if mode=1 then
     result:=RGB(r,g,b) else
     result:=RGB(b,g,r);
end;

procedure DrawPixelFast(Bitmap: TBitmap; X, Y: Integer; Color: TColor);
var
  ScanLine: PByteArray;
  BytesPerPixel: Integer;
begin
  if (X < 0) or (X >= Bitmap.Width) or (Y < 0) or (Y >= Bitmap.Height) then
    Exit;

  BytesPerPixel := 3;//Bitmap.PixelFormat div 8;
  ScanLine := Bitmap.ScanLine[Y];
  // Проверка на случай использования палитры (PixelFormat = pf8Bit)
  if BytesPerPixel = 1 then
    ScanLine[X] := ColorToRGB(Color)
  else
  begin
    ScanLine[X * BytesPerPixel] := GetBValue(Color);
    ScanLine[X * BytesPerPixel + 1] := GetGValue(Color);
    ScanLine[X * BytesPerPixel + 2] := GetRValue(Color);
    //if BytesPerPixel = 4 then
    //  ScanLine[X * BytesPerPixel + 3] := GetAValue(Color);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var x,y:integer;
  oldX,oldY,newX,newY:extended;
  c:TColor;
begin
if first then
begin
Bitmap1 := TBitmap.Create;
    Bitmap1.Width := ImageIn.Picture.Bitmap.Width;
    Bitmap1.Height := ImageIn.Picture.Bitmap.Height;
    Bitmap1.PixelFormat := pf24bit;
Bitmap2 := TBitmap.Create;
    Bitmap2.Width := ImageOut.Picture.Bitmap.Width;
    Bitmap2.Height := ImageOut.Picture.Bitmap.Height;
    Bitmap2.PixelFormat := pf24bit;
end;
for x := 0 to ImageIn.Picture.Bitmap.Width do
  for y := 0 to ImageIn.Picture.Bitmap.Height do
  begin
    oldX:=2*(x-ImageIn.Picture.Bitmap.Width/2);
    oldY:=2*(ImageIn.Picture.Bitmap.Height/2-y);
    if first then
     begin
      c:=getRGB(oldX,oldY,1);
      //ImageIn.Picture.Bitmap.Canvas.Pixels[x,y]:=c;
      DrawPixelFast(Bitmap1, x, y, c);
     end;
    transformation(oldX,oldY,newX,newY);
    c:=getRGB(newX,newY,2);
    //ImageOut.Picture.Bitmap.Canvas.Pixels[x,y]:=c;
    ///}DrawPixelFast(Bitmap2, x, y, c);
    {!}Plot1(x, y, c);
    retransformation(oldX,oldY,newX,newY);
    c:=getRGB(newX,newY,2);
       Plot2(x, y, c);
  end;
  if first then
   begin
    ImageIn.Picture.Bitmap.Assign(Bitmap1);
    first:=false;
   end;
  ///}ImageOut.Picture.Bitmap.Assign(Bitmap2);
    {!}DrawToDC1(PaintBox1.Canvas.Handle, 0, 0, W, H);
       DrawToDC2(PaintBox2.Canvas.Handle, 0, 0, W, H);
//   Bitmap1.Free;
//   Bitmap2.Free;
end;

procedure TForm1.FormClick(Sender: TObject);
begin
close;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  jpeg:TJpegImage;
  bmp:TBitmap;
begin
{ jpeg:=TJpegImage.Create;
  bmp:=TBitmap.Create;
  jpeg.LoadFromFile('1.jpg');
  bmp.Assign(jpeg);
  jpeg.Free;
  //рисуем на канве битмапа
  bmp.Canvas.Rectangle(0,0,100,100); //что рисовать не важно
  bmp.Free;   }
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
timer1.Enabled:=false;
//MouseMove([],512,640);
SetCursorPos(824,664);
Button1.Click;
end;

procedure TForm1.Transformation(za,zb:extended;var newX,newY:extended);
var upA,upB,downA,downB,norma:extended;
begin
upA:=z1a+za;
upB:=z1b+zb;
downA:=1+z1a*za+z1b*zb;
downB:=z1a*zb-z1b*za;
norma:=downA*downA+downB*downB;
if norma=0 then
  begin
   if (upA*downA+upB*downB)=0 then newX:=1 else newX:=0;
   if (upB*downA-upA*downB)=0 then newY:=1 else newY:=0;
  end else
  begin
   newX:=(upA*downA+upB*downB)/norma;
   newY:=(upB*downA-upA*downB)/norma;
  end;
end;

procedure TForm1.Panel1Click(Sender: TObject);
var x,y,tx,ty:integer;
    oldX,oldY,newX,newY:extended;
    c:TColor;
begin
timer1.Enabled:=true;
exit;
//ImageIn.Invalidate;
for x := 0 to round(int(ImageIn.Picture.Bitmap.Width/10)) do
  for y := 0 to round(int(ImageIn.Picture.Bitmap.Height/10)) do
   begin
    c:=ImageIn.Picture.Bitmap.Canvas.Pixels[10*x,10*y];
    oldX:=(10*x-ImageIn.Picture.Bitmap.Width/2)/0.9;
    oldY:=(ImageIn.Picture.Bitmap.Height/2-10*y)/0.9;
    transformation(oldX,oldY,newX,newY);
    tx:=round(int(ImageIn.Picture.Bitmap.Width/2+9*newX));
    ty:=round(int(ImageIn.Picture.Bitmap.Height/2-9*newY));
    //ImageOut.Picture.Bitmap.Canvas.Pixels[tx,ty]:=c;
    ImageOut.Picture.Bitmap.Canvas.MoveTo(10*x,10*y);
    ImageOut.Picture.Bitmap.Canvas.LineTo(tx,ty);
   end;
//ImageIn.Update;
//ImageOut.Repaint;
end;

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var sx,sy:string;
begin
z1a:=(X-320/2)/20000;
z1b:=(256/2-Y)/20000;
  Str(z1a*100:2:2,sx);
  Str(z1b*100:2:2,sy);
if (z1a>=0)and(z1b>=0) then StaticText1.Caption:='z₁:=+'+sx+'+'+sy+'i' else
if (z1a< 0)and(z1b< 0) then StaticText1.Caption:='z₁:='+sx+sy+'i'      else
if (z1a< 0)and(z1b>=0) then StaticText1.Caption:='z₁:='+sx+'+'+sy+'i'  else
                             StaticText1.Caption:='z₁:=+'+sx+sy+'i';

Button1.Click();
end;

initialization

with BitsInfo1, bmiHeader do
begin
  biSize := SizeOf (bmiHeader);
  biWidth := 0;
  biHeight := 0;
  biPlanes := 1;
  biBitCount := 32;
  biCompression := BI_RGB;
  biSizeImage := 0;
  biXPelsPerMeter := 0;
  biYPelsPerMeter := 0;
  biClrUsed := 0;
  biClrImportant := 0;
end;
with BitsInfo2, bmiHeader do
begin
  biSize := SizeOf (bmiHeader);
  biWidth := 0;
  biHeight := 0;
  biPlanes := 1;
  biBitCount := 32;
  biCompression := BI_RGB;
  biSizeImage := 0;
  biXPelsPerMeter := 0;
  biYPelsPerMeter := 0;
  biClrUsed := 0;
  biClrImportant := 0;
end;

//MessageBox(0,'клик на белом для выхода, клик на сером для центровки','',0);
end.

 
 
 [ Сообщений: 4 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group