Random Polygons, Surfaces, Segments for Automated Software Tests

Geometry programming: Degenerate cases, numeric issues and unexpected geometric settings make a developer’s life hard. Automated software stress tests with random data are essential to discover bugs early. But creating random polygons without self-intersections or even random surfaces is for example not trivial. For convenient debugging the module testDataGenerators can be used to create repeatable

  • Random surfaces
  • Random polygons
  • Random segments
  • Random point clouds
  • Random numbers
  • Polylines from sine functions
  • Circles

Repeatability

What you likely want is repeatable randomness so that you can later regenerate the data that has crashed your software. For this reason all random object generators take a seed value to initialize the internal random number generator. A certain seed value leads always to the same sequence of objects. Only when the special seed value 0 is passed then random sequences of objects are created. Typically you will have a test loop like this:

void test()
{
  for(int seed=1;seed<1000000;++seed)
  {
    vector<...> vRandomObjects;
    generateRandom...(..,..,..,vRandomObjects,seed);
    bool bResult=mySoftware(vRandomObjects);
    if(!bResult)
    {
      cout<<"Error, seed="<<seed<<endl;
      exit(1);
    }
  }
}

Random numbers

The code below creates two sequences of random numbers for seed=0, for seed=1 and seed=2. The sequences for seed=0 differ while the ones for non-zero seeds are reproducable.

size_t num(5);
double min(-100.0);
double max(100.0);

for(int seed=0;seed<3;++seed)
{
  cout<<"seed "<<seed<<": "<<endl;
  vector<double> vRandomNumbers0;
  vector<double> vRandomNumbers1;
  generateRandomNumbers(num,min,max,vRandomNumbers0,seed);
  generateRandomNumbers(num,min,max,vRandomNumbers1,seed);

  for(size_t i=0;i<vRandomNumbers0.size();++i)
  {
    cout<<vRandomNumbers0[i]<<" ";
  }
  for(size_t i=0;i<vRandomNumbers1.size();++i)
  {
    cout<<vRandomNumbers1[i]<<" ";
  }
}
seed 0:
67.6368 -81.1831 24.9494 -74.8083 34.5807
67.9391 37.8979 74.0638 89.8681 -35.0061
seed 1:
68.0375 -21.1234 56.6198 59.688 82.3295
68.0375 -21.1234 56.6198 59.688 82.3295
seed 2:
40.1953 61.9353 -82.2409 -75.7042 -30.3386
40.1953 61.9353 -82.2409 -75.7042 -30.3386

Random polygons

Creating and visualizing a random simple polygon works similarly. Choose the number of segments, the min- and max-coordinates and you’re done:

void randomPolygon()
{
  size_t num(50);
  double min(-100.0);
  double max(100.0);
  int seed(0); // seed=0 for real randomness

  vector<Segment2> vRandomPolygon;
  generateRandomPolygon(num,min,max,vRandomPolygon,seed);
  Visualizer2 vis("rndPolygon.ps");
  vis.addObject(vRandomPolygon,Color(CBLACK));
  vis.writeFile();
}
Random Polygons

Random segments

The code below creates random segments. Intersections are possible.

void randomSegments()
{
  size_t num(50);
  double min(-100.0);
  double max(100.0);
  double maxLen(50);
  int seed(0);// seed=0 for real randomness

  vector<Segment2> vRandomSegments;
  generateRandomSegments(num,min,max,maxLen,vRandomSegments,seed);
  Visualizer2 vis("rndSegments.ps");
  vis.addObject(vRandomSegments,Color(CBLACK));
  vis.writeFile();
}

Random Segments

Random points

void randomPoints()
{
  size_t num(1000);
  double min(-100.0);
  double max(100.0);
  int seed(0); // seed=0 for real randomness

  vector<Point2> vRandomPoints;
  generateRandomPoints(num,min,max,vRandomPoints,seed);
  Visualizer2 vis("rndPoints.ps");
  vis.addObject(vRandomPoints,Color(CBLACK));
  vis.writeFile();
}

Random Points

Circles

The generateCircle(…) command creates points on a given circle. No randomness in this command. The code below creates two circles, one is scaled in x direction.

void circles()
{
  int numPoints(50);
  double centerX(0.0);
  double centerY(0.0);
  double radiusX(1.0);
  double radiusY(1.0);
  vector<Point2> vCirclePoints0;
  vector<Point2> vCirclePoints1;
  generateCircle(numPoints,centerX,centerY,radiusX,radiusY,vCirclePoints0);
  generateCircle(2*numPoints,centerX,centerY,2*radiusX,radiusY,vCirclePoints1);

  Visualizer2 vis("circles.ps");
  vis.addObject(vCirclePoints0,Color(CBLUE));
  vis.addObject(vCirclePoints1,Color(CGREEN));
  vis.writeFile();
}

Points on Circles

Sine functions

The example below generates four curves. The base function is sin(x), but x and y can be swapped and independent offsets and scale factors can be applied for x- and y-direction.


void sineFunctions()
{
  int numSegments(50);
  int numPeriods(1);
  double xOffset(0);
  double yOffset(0);
  double xFactor(1.0);
  double yFactor(1.0);
  bool bSwapXY(false);

  vector<Segment2> vSineSegments0;
  vector<Segment2> vSineSegments1;
  vector<Segment2> vSineSegments2;
  vector<Segment2> vSineSegments3;
  generateSineSegments(numSegments,numPeriods,xOffset,yOffset,xFactor,yFactor,bSwapXY,vSineSegments0);
  generateSineSegments(numSegments,numPeriods,3.14159/2.0,yOffset,xFactor,yFactor,bSwapXY,vSineSegments1);
  generateSineSegments(numSegments,3,xOffset,yOffset,.33,yFactor,true,vSineSegments2);
  generateSineSegments(numSegments,3,xOffset,yOffset,.33,-yFactor,true,vSineSegments3);

  Visualizer2 vis("sine.ps");
  vis.addObject(vSineSegments0,Color(CBLUE));
  vis.addObject(vSineSegments1,Color(CGREEN));
  vis.addObject(vSineSegments2,Color(CRED));
  vis.addObject(vSineSegments3,Color(CBLACK));
  vis.writeFile();
}

Polylines from Sine Functions

Random Surfaces

Random surfaces are a 2.5D topic and thus we leave the source file /examples_2D/randomData.cpp now. Creation of random surfaces is implement in the example code Cut-and-Fill. For completeness the used function is reviewed here:


void randomSurface()
{
	vector<Point2> vRndSurfacePoints;
	generateRandomSurfacePoints(
		70, // numPointsX
		70, // numPointsY
		15, // numCenters
		0,0,-100,1000,1000,100, // Bounds xmin,ymin,zmin,xmax,ymax,zmax
		vRndSurfacePoints,// Output vector
		1// Seed
	);
	Fade_2D dt;
	dt.insert(vRndSurfacePoints);
	dt.showGeomview("randomSurface.list");
}

The function call above creates a 70×70 grid of points whose XY-range is (0,0)-(1000,1000). The elevations Z of these points are in the range (-100,+100). The numCenters parameter determines the waviness of the surface. The showGeomview command is convenient for Geomview users. But you can alternatively use writeObj() or writeWebScene() to visualize the result.

Random Surface 2.5D

Random Surface Triangulation, 2.5D

Spread the word. Share this post!

Leave A Reply

Your email address will not be published. Required fields are marked *

*

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close