POV-Ray : Newsgroups : povray.programming : random numbers in c++ : random numbers in c++ Server Time
25 Apr 2024 11:11:34 EDT (-0400)
  random numbers in c++  
From: Anthony D  Baye
Date: 25 Aug 2010 00:15:00
Message: <web.4c74984fbae2e676507e8a090@news.povray.org>
I'm working on an implementation of the Diamond-Square algorithm, and it seems
to be working... sort of, but for two things.

First, I'm getting seriously large pixel values.  I've been trying to clamp them
between 0 and 255 inclusive, but it's not working the way I hoped it would.

Second my random number function. (I've attached the source file, but I'll
reiterate the function here) I'm using the rand() function from cstdlib:

double Random(double r)
{
     double rNum;

     rNum = r - (2*r)/(rand()%65535);

     return rNum;
}

theoretically, this should generate a random number between -r and r, but I'm
only getting positive values within a small range.  reducing the range of random
values to 100 or less seems to generate more negative numbers but problems
persist.

At the moment, the largest problem seems to be clamping the values.

the code outputs the result to a pgm file with a depth of 8 bits

changing the range multiplier seems to have some interesting effects, but I'm
not sure I like the results.

Any help would be appreciated.

A.D.B.

Code follows:

/******************************************************
* Name: Main.cpp                   Date: Aug. 21, 2010 *
*                                                      *
* Auth: Anthony D. Baye                                *
* Desc: basic implementation of the Diamond-Square     *
*    Algorithm.                                        *
*                                                      *
 ******************************************************/
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <fstream>
#include <cmath>
#include "grids.h"
using namespace std;

double Random(double);
void seedGrid(grid<double> &, int);
void diamond_square(grid<double> &);
void print(grid<double>);
void save(grid<double>);

int main(int argc, char** argv)
{
     unsigned long int height, width;
     grid<double> canvas;

     srand(65535);
     height = strtoul(argv[0],NULL,0);
     width = strtoul(argv[1],NULL,0);

     canvas.create(width, width);
/*
     canvas.at(0,0) = 25;
     canvas.at(canvas.width()-1, 0) = 25;
     canvas.at(0, canvas.height()-1) = 25;
     canvas.at(canvas.width()-1, canvas.height()-1) = 255;
*/
//     seedGrid(canvas, 30);

     diamond_square(canvas);

     save(canvas);

     return 0;
}

double Random(double r)
{
     double rNum;
     int n = rand()%100;

     if(n == 0)
          n++;
     rNum = r - ((2*r)/n);
//     cout << rNum << "   " << n << endl;

     return rNum;
}

void seedGrid(grid<double> &canvas, int N)
{
     int x, y;

     while(N > 0)
     {
          x = int(Random(1.0)*canvas.width() + 0.5);
          y = int(Random(1.0)*canvas.height() + 0.5);

          if(x > canvas.width())
               x = canvas.width();
          if(x < 0)
               x = 0;
          if(y > canvas.height())
               y = canvas.height();
          if(y < 0)
               y = 0;

          canvas.at(y,x) = Random(1.0)*255;
          N--;
     }
}

void diamond_square(grid<double> &canvas)
{
     int sLen = canvas.width();
     int hS = sLen / 2;
     unsigned long int x, y;
     double avg, range;

     srand(time(NULL));
     range = 1.0;
     while(sLen >= 2)
     {
          int hS = sLen / 2;

          for(y = 0; y < canvas.height()-1; y+=sLen)
          {
               for(x = 0; x < canvas.width()-1; x+=sLen)
               {
                    avg =
                         canvas.at(y,x) +
                         canvas.at(y,x+sLen) +
                         canvas.at(y+sLen,x+sLen) +
                         canvas.at(y+sLen,x);
                    avg /= 4;

                    canvas.at(y+hS, x+hS) = avg + Random(range)*255;
               }
          }

          for(y = 0; y < canvas.height()-1; y+=hS)
          {
               for(x = (y+hS)%sLen; x < canvas.width()-1; x+=sLen)
               {
                    avg =
                         canvas.at(y,(x+hS)%canvas.width()) +
                         canvas.at(y,(x-hS+canvas.width())%canvas.width()) +
                         canvas.at((y+hS)%canvas.height(),x) +
                         canvas.at((y-hS+canvas.height())%canvas.height(),x);
                    avg /= 4;

                    canvas.at(y,x) = avg + Random(range)*255;
               }
          }

          sLen /= 2;
          range /= 2;
     }
}

void print(grid<double> canvas)
{
     int x, y;

     for(y=0; y<canvas.height(); y++)
     {
          for(x=0; x<canvas.width(); x++)
          {
               cout << setw(3) << right << canvas.at(y,x) <<
                    setw(2) << ", ";
          }
          cout <<  endl;
     }

}

void save(grid<double> canvas)
{
     int x, y;
     fstream fout;

     fout.open("lscape.pgm", ios::out);
     fout << "P2" << endl;
     fout << canvas.width() << endl;
     fout << canvas.height() << endl;
     fout << "255" << endl;
     for(y=0; y<canvas.height(); y++)
     {
          for(x=0; x<canvas.width(); x++)
          {
               fout << setw(10) << right << canvas.at(y,x) <<
                    setw(1) << " ";
          }
          fout <<  endl;
     }
     fout.close();

}

grids.h:

// Name: grids.h

// Vers: 1.0b

// Auth: Anthony D. Baye

/* Desc: Creates a linearly-addressed 2D array of a given datatype.

 Handles insertion and retrieval of values into and from the array,

 making sure that the index values do not overstep the array bounds.

*/



#ifndef _GRID_TEMP_H_

#define _GRID_TEMP_H_



#include <iostream>

using namespace std;



template<class _TY>

class grid

{

public:

 grid();

 grid(grid<_TY> &c);

 ~grid();



 int create(unsigned long int hgt, unsigned long int wid);

 _TY &at(unsigned long int row, unsigned long int col);

 _TY &at(unsigned long int pos);

 unsigned long int height() const;

 unsigned long int width() const;

 unsigned long int size() const;

 bool destroy();

 bool isEmpty() const;



private:

 _TY **cptr;

 unsigned long int H, W, S;

 _TY Error;

};



/***************************************************
***
* Name: grid()                     Date: Thu. 06-12-08 *

*                                                      *

* Auth: Anthony D. Baye                                *
* Desc: Constructor function for template class.       *

* Sets pointers to NULL and size values to zero. *

 ******************************************************/
template<class _TY>

grid<_TY>::grid()

{

 cptr = NULL;

 //Error = NULL;

 H = 0;

 W = 0;

 S = 0;

};



/***************************************************

* Name: grid()                  Date: Thu. 06-12-08 *

*                                                   *

* Auth: Anthony D. Baye                             *
* Desc: Copy constructor function for template grid *

*       class.                                      *

 ***************************************************/
template<class _TY>

grid<_TY>::grid(grid<_TY> &c)

{

 unsigned long int i, j;



 cptr = NULL;

 //Error = NULL;

 H = 0;

 W = 0;

 S = 0;



 create(c.height(), c.width());

 for(i=0; i<H; i++)

  for(j=0; j<W; j++)

   cptr[i][j] = c.at(i, j);



};



template<class _TY>

grid<_TY>::~grid()

{

 if(cptr != NULL)

  destroy();

};



template<class _TY>

bool grid<_TY>::isEmpty() const

{

 return (cptr == NULL);

};



template<class _TY>

bool grid<_TY>::destroy()

{

 if(cptr == NULL)

  return false;



 delete cptr[0];

 delete [] cptr;

 cptr = NULL;



 return true;

};



/***************************************************

* Name: create()                 Date: Thu. 6-12-08 *

*                                                   *

* Auth: Anthony D. Baye                             *
* Desc: Creates a grid object with the dimesions    *

* (hgt)x(wid) returns an integer flag.        *

*                                                   *

* Flag:                                             *

*     0 -> Execution complete, no errors.           *

*     1 -> Execution terminated, grid exists.       *

*    -1 -> Execution terminated, out of memory.     *

 ***************************************************/

template<class _TY>

int grid<_TY>::create(unsigned long int hgt, unsigned long int wid)

{

 unsigned long int i, j;



 if(cptr != NULL)

  return 1;



 // Initialize the pointer to the number of rows.

 cptr = new(nothrow) _TY *[hgt];

 if(cptr == NULL)

  return -1;



 S = hgt * wid; // Calculate the number of entries in the array, and store the
number in private variable

 cptr[0] = new(nothrow) _TY [S]; // Initialize ptr[0] to the full size of the
array. Clean up if fail.

 if(cptr[0] == NULL)

 {

  S = 0;

  delete [] cptr;

  return -1;

 }



 // Store the dimensions in private variables.

 H = hgt;

 W = wid;

 // Step through the rows.

 for(i=1; i<H; i++)

 {

  // Step through row 0.

  for(j=0; j<S; j++)

  {

   // If j is a multiple of columns and rows, set the contents of ptr[i] to the
address of ptr[0][j].

   if(j == (W*i))

    cptr[i] = &cptr[0][j];

  }

 }



 return 0; // Home again, home again...

};





/***************************************************

* Name: at()                  Date: Thu. 6-12-08    *

*                                                   *

* Auth: Anthony D. Baye                             *

* Args: unsigned long int row, col                  *

* Desc: If row and col are within the bounds of the *

* array, returns a pointer to cptr[row][col]. *

* Otherwise, returns address to Error space.  *

 ***************************************************/

template<class _TY>

_TY &grid<_TY>::at(unsigned long int row, unsigned long int col)

{

 if(cptr == NULL || col >= W || row >= H)

  return Error;



 return cptr[row][col];

};



/*******************************************************

* Name: at()                         Date: Thu. 6-12-08 *

*                                                       *

* Auth: Anthony D. Baye                                 *

* Args: int x, int y                                    *

* Desc: Performs same function as above, but returns    *
*     Nth index from the beginning of the array.  This  *

*     is possible, because of the way that the array *

*     is addressed.  Returns Error space if pos is out  *

*     of bounds                                         *

 *******************************************************/

template<class _TY>

_TY &grid<_TY>::at(unsigned long int pos)

{

 if(cptr == NULL || pos >= S)

  return Error;



 return cptr[0][pos];

};



template<class _TY>

unsigned long int grid<_TY>::height() const

{

 return H;

};



template<class _TY>

unsigned long int grid<_TY>::width() const

{

 return W;

};



template<class _TY>

unsigned long int grid<_TY>::size() const

{

 return S;

};

#endif


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.