zoukankan      html  css  js  c++  java
  • Visualizing wave interference using FireMonkey(很美)

     

    Visualizing wave interference using FireMonkey

    By: Anders Ohlsson

    Abstract: This article discusses how you can generate your own dynamic 3-dimensional mesh for visualizing wave interference using Delphi XE2 and FireMonkey.

        Prerequisites!

        The wave function

    The wave function we'll use in this article is:

             f(x,y) = A*sin(1/L*r-v*t)

    where:

    • (x,y) = observation point
    • A = amplitude
    • L = wave length
    • r = distance between wave center and observation point
    • v = velocity of wave propagation
    • t = time

    In Delphi it simply becomes:

    function f(x,y : Double) : Double;
    begin
      f := Amplitude*Sin(1/Length*Sqrt(Sqr(x-PosX)+Sqr(y-PosY))-Speed*t);
    end;
    

    Note: It should be noted that this function simply gives us the state of equilibrium. We're completely ignoring starting scenarios and the fact that waves die out over time and distance.

    The screen shot below shows one wave:

        Hide imageClick to see full-sized image

    Two waves interfering with each other:

    Hide image
    Click to see full-sized image

    And 4 waves while we're at it:

    Hide image
    Click to see full-sized image

        Generating the mesh

    In order to generate the mesh, we borrow the code from my previous article, and modify it slightly to give it a time parameter:

    procedure TForm1.GenerateWave(t : Double);
      function f(x,y : Double) : Double;
      var
        i : Integer;
      begin
        Result := 0;
        for i:=0 to 3 do
          with Wave[i] do
            if Enabled then
              Result := Result+Amplitude*Sin(1/Length*Sqrt(Sqr(x-PosX)+Sqr(y-PosY))-Speed*t);
      end;
    const
      MaxX = 30;
      MaxZ = 30;
    var
      u, v : Double;
      px, py, pz : array [0..3] of Double;
      d : Double;
      NP, NI : Integer;
      BMP : TBitmap;
      k : Integer;
    begin
      d := 0.5;
      NP := 0;
      NI := 0;
    
      Mesh1.Data.VertexBuffer.Length := Round(2*MaxX*2*MaxZ/d/d)*4;
      Mesh1.Data.IndexBuffer.Length := Round(2*MaxX*2*MaxZ/d/d)*6;
    
      BMP := TBitmap.Create(1,360);
      for k := 0 to 359 do
        BMP.Pixels[0,k] := CorrectColor(HSLtoRGB(k/360,0.75,0.5));
    
      u := -MaxX;
      while u < MaxX do begin
        v := -MaxZ;
        while v < MaxZ do begin
          px[0] := u;
          pz[0] := v;
          py[0] := f(px[0],pz[0]);
    
          px[1] := u+d;
          pz[1] := v;
          py[1] := f(px[1],pz[1]);
    
          px[2] := u+d;
          pz[2] := v+d;
          py[2] := f(px[2],pz[2]);
    
          px[3] := u;
          pz[3] := v+d;
          py[3] := f(px[3],pz[3]);
    
          with Mesh1.Data do begin
            // Set the points
            with VertexBuffer do begin
              Vertices[NP+0] := Point3D(px[0],py[0],pz[0]);
              Vertices[NP+1] := Point3D(px[1],py[1],pz[1]);
              Vertices[NP+2] := Point3D(px[2],py[2],pz[2]);
              Vertices[NP+3] := Point3D(px[3],py[3],pz[3]);
            end;
    
            // Map the colors
            with VertexBuffer do begin
              TexCoord0[NP+0] := PointF(0,(py[0]+35)/45);
              TexCoord0[NP+1] := PointF(0,(py[1]+35)/45);
              TexCoord0[NP+2] := PointF(0,(py[2]+35)/45);
              TexCoord0[NP+3] := PointF(0,(py[3]+35)/45);
            end;
    
            // Map the triangles
            IndexBuffer[NI+0] := NP+1;
            IndexBuffer[NI+1] := NP+2;
            IndexBuffer[NI+2] := NP+3;
            IndexBuffer[NI+3] := NP+3;
            IndexBuffer[NI+4] := NP+0;
            IndexBuffer[NI+5] := NP+1;
          end;
    
          NP := NP+4;
          NI := NI+6;
          v := v+d;
        end;
        u := u+d;
      end;
    
      Mesh1.Material.Texture := BMP;
    end;
    

        Animating the mesh

    The above code generates a "snap shot" of the wave interaction between 4 waves at any time t.

    Animating the wave is simply a matter of using a timer to increment time and re-generating the mesh over and over again:

    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      GenerateWave(t);
      t := t+0.1;
    end;
    

    The waves are represented by this record:

    type
      TWave = record
        Enabled : Boolean;
        Amplitude : Double;
        Length : Double;
        PosX : Double;
        PosY : Double;
        Speed : Double;
      end;
    

    In the demo project that accompanies this article, I have declared 4 starting waves like so:

    var
      Wave : array [0..3] of TWave = ((Enabled: False; Amplitude: 1; Length: 1; PosX: -20; PosY: -20; Speed: 1),
                                      (Enabled: False; Amplitude: 1; Length: 1; PosX: +20; PosY: -20; Speed: 1),
                                      (Enabled: False; Amplitude: 1; Length: 1; PosX: +20; PosY: +20; Speed: 1),
                                      (Enabled: False; Amplitude: 1; Length: 1; PosX: -20; PosY: +20; Speed: 1));
    

    Note that all 4 waves have the same properties, except that their origins are spread across the coordinate system. Specifically they're located in (-20,-20), (+20,-20), (+20,+20) and (-20,+20).

        Demo application

    You can find my demo application in CodeCentral.

    http://edn.embarcadero.com/article/42012

  • 相关阅读:
    wamp+phpzendstudio配置xdebug57%解决办法
    【linux学习问题解决】使用aptget安装软件出现unable to locate package的解决办法
    【linux LAMP平台安装】写在前面(一)
    【linux学习问题解决】更改字符界面大小(转)
    [phpcms二次开发]phpcms生成栏目出错,转到模版页面
    [phpcms二次开发]给url规则添加可用更多自定义可用变量
    [phpcms二次开发]实现获取路径linux与windows路径兼容
    控件注册 利用资源文件将dll、ocx打包进exe文件(转)
    C#串口通信:MSComm控件使用详解
    改善C#程序的建议1:非用ICloneable不可的理由
  • 原文地址:https://www.cnblogs.com/findumars/p/10247697.html
Copyright © 2011-2022 走看看