Generateur de complexes aleatoires

Description

Voila un petit programme qui permet de montrer
la repartition de complexes dans le cercle unite selon deux methodes.
La seconde etant celle qui permet une repartition uniforme,
celle qui peut etre utile dans certains algorihtmes.
La premiere est une "mauvaise" repatition car il y a une forte
densite de complexes autour de 0.

On part du principe que l'on a un generateur de nombres aleatoires
flottants entre deux valeurs. Le premiere methode represente le
premier algorithme qui vient a l'esprit : uniforme pour l'angle
et uniforme pour le rayon (du complexe considere). celle-ci etant
evidemment erronee car elle ne tient pas compte tu fais que plus
le rayon augmente, plus la surface balayee est grande (aire~rayon²).
La vraie methode consiste a prendre l'angle uniformement, mais a
prendre pour rayon le maximum de deux uniformes, ce qui compensera
le phenomene explique ci-dessus. Pour se laisser s'en convaicre,
executer le programme ...

Source / Exemple :


#ifndef _UTIL_H_
	#include "util.h"
#endif // _UTIL_H_

#ifndef _MATH_H_
	#include "math.h"
#endif // _MATH_H_

#ifndef _LIST_H_
	#include "list.h"
#endif // _LIST_H_

#ifndef _WINUTIL_H_
	#include "winutil.h"
#endif // _WINUTIL_H_

//-------------------------------------------------
#define FUNC_RATIO            myMinAspectRatio
#define MSG_USER_NEW_RANDOM   1000

#define NB_ITERATION          10000
#define NB_DIVISION_R         4
#define NB_DIVISION_ANGLE     8

//-------------------------------------------------
// WND_PROC
//-------------------------------------------------
int WndProc(P_MY_WINDOW myWindow,HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
static MY_GRAPH   graph1,graph2;
static P_MY_HDC   hdcMem,hdcParent;

switch(iMsg)
  {
  // creation de la fentre
	case WM_CREATE:
    {
    RECT    rcWindow;
    RECTD   rcView;
    double  frame;

    myWindow->bResizedWindow   = FALSE;
    myWindow->bUseBackBuffer   = FALSE;
    myWindow->colorBackGround  = COLOR_BACK_GROUND_NO_ERASE;

    hdcParent = myCreateDCIndirect(hwnd,FALSE);
    hdcMem    = myCreateDC(GetHdc(hdcParent),TRUE);
    GetClientRect(hwnd,&rcWindow);
    myPushBitmap(hdcMem,hdcParent,myWidthRect(&rcWindow),myHeightRect(&rcWindow));
    myDeleteDCIndirect(hdcParent);

    frame = 0.1;

    mySetWindowGraph(&graph1,&rcWindow);
    rcView.left     = -1.  -   frame;
    rcView.top      = +1.  +   frame;
    rcView.right    = +3.  + 3*frame;
    rcView.bottom   = -1.  -   frame;
    mySetViewGraph(&graph1,&rcView,FUNC_RATIO,NULL);

    mySetWindowGraph(&graph2,&rcWindow);
    rcView.left     = -3.  - 3*frame;
    rcView.top      = +1.  +   frame;
    rcView.right    = +1.  +   frame;
    rcView.bottom   = -1.  -   frame;
    mySetViewGraph(&graph2,&rcView,FUNC_RATIO,NULL);

    SendMessage(hwnd,WM_USER,MSG_USER_NEW_RANDOM,IRRELEVANT);
    
    break;
    }
  // changement de la taille
  case WM_SIZE:
    {
    RECT  rcWindow;

    GetClientRect(hwnd,&rcWindow);

    mySetWindowGraph(&graph1,&rcWindow);
    mySetViewGraph(&graph1,NULL,FUNC_RATIO,NULL);

    mySetWindowGraph(&graph2,&rcWindow);
    mySetViewGraph(&graph2,NULL,FUNC_RATIO,NULL);
    break;
    }
  // bouton gauche de la souris
  case WM_LBUTTONDOWN:
    {
    SendMessage(hwnd,WM_USER,MSG_USER_NEW_RANDOM,IRRELEVANT);
    myRepaintWindow(hwnd);
    break;
    }
  // bouton droit de la souris
  // les touches
  case WM_KEYDOWN:
    {
    switch((int)wParam)
      {
      default:
        break;
      }
    break;
    }
  // messages utilisateurs
  case WM_USER:
    {
    switch(LOWORD(wParam))
      {
      case MSG_USER_NEW_RANDOM:
        {
        int   i;
        RECT  rc;
        int   iMax,width;

        // on efface le fond par du blanc
        myPushBrush(hdcMem,BS_SOLID,RGB_WHITE,IRRELEVANT);
        GetClientRect(hwnd,&rc);
        myFillRect(hdcMem,&rc);
        myPopBrush(hdcMem);

        width   = 2;
        iMax    = NB_ITERATION;
  
        // methode du <graph1> :
        //   module   : uniforme entre 0 et 1
        //   argument : uniforme entre 0 et 2.pi
        myPushPen(hdcMem,PS_SOLID,width,RGB_RED);
        for(i=0;i<iMax;i++)
          {
          double r,t,x,y;
          r = RandomDouble(0.,1.);
          t = RandomDouble(0.,2.*MATH_PI);
          x = r*cos(t);
          y = r*sin(t);
          myDrawPointGraph(hdcMem,&graph1,x,y);
          }
        myPopPen(hdcMem);
        SetBkColor(GetHdc(hdcMem),RGB_YELLOW);

        // methode du <graph2> :
        //   module   : maximum etre deux uniformes entre 0 et 1
        //   argument : uniforme entre 0 et 2.pi
        myPushPen(hdcMem,PS_SOLID,width,RGB_BLUE);
        for(i=0;i<iMax;i++)
          {
          double r,r1,r2,t,x,y;
          r1 = RandomDouble(0.,1.);
          r2 = RandomDouble(0.,1.);
          r  = max(r1,r2);
          t  = RandomDouble(0.,2.*MATH_PI);
          x  = r*cos(t);
          y  = r*sin(t);
          myDrawPointGraph(hdcMem,&graph2,x,y);
          }
        myPopPen(hdcMem);

        // les petits commetaires
          {
          int cx,cy;
          cx = -8;
          cy = -20;
          myDrawTextGraph(hdcMem,&graph1,"Courrier New",700,cx,cy,0.,0.5,1.,1.," complexes centrés ");
          myDrawTextGraph(hdcMem,&graph2,"Courrier New",700,cx,cy,0.,0.5,1.,1.," complexes uniformément répartis ");
          myDrawTextGraph(hdcMem,&graph1,"Courrier New",700,cx,cy,0.,0.5,-1.,0.," [r=Uniform(0,1),t=Uniform(0,2.Pi)] ");
          myDrawTextGraph(hdcMem,&graph2,"Courrier New",700,cx,cy,0.,0.5,-1.,0.," [r=Max(Uniform(0,1),Uniform(0,1)),t=Uniform(0,2.Pi)] ");
          }

        break;
        }
      }
    break;
    }
  // le commandes
  case WM_COMMAND:
    {
    switch(LOWORD(wParam))
      {
      }
    break;
    }
  // on dessine
	case WM_PAINT:
    {
    P_MY_HDC  hdc;
    int       cx,cy;
    RECT      rc;

    cx  = LOWORD(lParam);
    cy  = HIWORD(lParam);
    hdc = (P_MY_HDC)wParam;

    // on dessine les points
    GetClientRect(hwnd,&rc);
    myStretchBlt(hdc,&rc,hdcMem,&rc,SRCCOPY);

    // on dessine les axes et le cercle
    myPushBrush(hdc,BS_NULL,IRRELEVANT,IRRELEVANT);
    myPushPen(hdc,PS_SOLID,0,RGB_DARKGRAY);
      {
      RECTD   rcCircle;
      double  r,dr;
      double  t,dt;

      // axes
      dt = 2.*MATH_PI/NB_DIVISION_ANGLE;
      for(t=0.;t<MATH_PI;t+=dt)
        {
        myDrawLineGraph(hdc,&graph1,cos(t),sin(t),-cos(t),-sin(t));
        myDrawLineGraph(hdc,&graph2,cos(t),sin(t),-cos(t),-sin(t));
        }
      // le cercle
      myPushPen(hdc,PS_SOLID,0,RGB_BLACK);
        r = 1.;
        mySetRectd(&rcCircle,-r,r,r,-r);
        myDrawEllipseGraph(hdc,&graph1,&rcCircle);
        myDrawEllipseGraph(hdc,&graph2,&rcCircle);
      myPopPen(hdc);

      dr = 1./NB_DIVISION_R;
      for(r=dr;r<1.;r+=dr)
        {
        mySetRectd(&rcCircle,-r,r,r,-r);
        myDrawEllipseGraph(hdc,&graph1,&rcCircle);
        myDrawEllipseGraph(hdc,&graph2,&rcCircle);
        }
      }
    myPopPen(hdc);
    myPopBrush(hdc);

		break;
    }
  // destruction de la fenetre
	case WM_DESTROY:
    {
    myPopBitmap(hdcMem);
    myDeleteDC(hdcMem);

    PostQuitMessage(0);
		break;
    }
  }

return 0;
} // WndProc()

//-------------------------------------------------
// WINMAIN
//-------------------------------------------------
int WINAPI WinMain(
                   HINSTANCE  hInstance,
                   HINSTANCE  hPrevInstance, 
                   LPSTR      lpszCmdLine,
                   int        iCmdShow
                   )       
{
InitializationLibUtil();
InitializationLibWinutil(hInstance);
  {
  HWND        hwnd;
  WNDCLASSEX  wc;
  RECT        rc;

  mySetDefaultWindowClass(&wc,hInstance);
  wc.lpszClassName  = "JCD_alea";
  mySetRectWH(&rc,0,0,1000,500);

  hwnd = myCreateWindow(&wc,
	                      "Complexes aléatoires dans le cercle unité",
                        WS_OVERLAPPEDWINDOW,
                        &rc,
                        TRUE,
                        TRUE,
	                      NULL,
                        NULL,
	                      0,
                        NULL,
	                      WndProc
                        );

  myRunWindow(hwnd,SW_SHOW);

  }
CloseLibUtil();
CloseLibWinutil();
CheckingClosingLibUtil();
CheckingClosingLibWinutil();
return 0 ;
} // WinMain()

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.