Categories

# Random Polygons, Surfaces and more – Example 9

When coding geometry, numerical errors and unexpected geometric settings occur frequently. Thus automated software testing with random geometric data is essential. But for example creating random polygons without self-intersection is not trivial at all. Therefore the module testDataGenerators is provided to create repeatable sequences of random geometric objects for software testing and debugging. These are for instance random surfaces, random polygons or random segments. Moreover generators for circles and polylines from sine functions exist.

## Repeatability

What you most likely want is repeatable randomness so that you can later re-generate the test data that crashed your software. For this reason, all random object generators take a `seed` value to statically initialize the internal random number generator. That means a specific seed value always results in the same sequence of objects. However, if the special seed value 0 is passed, the generated sequence will be different from call to call. Typically you will use a test loop like this:

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

## Random numbers

The code below creates two sequences of random numbers for `seed`=0, 1 and 2. According to the above said 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&lt;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. That is, you 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.writeFile();
}
```

## Random segments

The code below creates random segments which may also intersect each other.

```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.writeFile();
}```

## Random points

The code below creates random points in a specified bounding box.

```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.writeFile();
}```

## Circles

The generateCircle(…) command creates points on a given circle. In contrast to the above commands this one involves no randomness. 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);
vector<Point2> vCirclePoints0;
vector<Point2> vCirclePoints1;

Visualizer2 vis("circles.ps");
vis.writeFile();
}```

## Sine functions

This example 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.writeFile();
}```

## Random Surfaces

The test data generators work also with Fade2.5D where there is the additional possibility to generate random surfaces. This functionality is for instance used in the Example Cut-and-Fill and or completeness it 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
);
The function call above creates a 70×70 grid of points whose `x,y`-range is (0,0)-(1000,1000). These points have elevations `z` in the range (-100,+100). The `numCenters` parameter determines the waviness of the surface. Use `showGeomview()`, `writeObj()` or `writeWebScene()` to show a 3D scene of the result.