I am creating a game where a landscape is generated all of the generations work perfectly, a week ago I have created a basic 'forest' generation system which just is a for loop that takes a chunk, and places random amounts of trees in random locations. But that does not give the result I would like to achieve.
Code:
for(int t = 0; t <= randomForTrees.nextInt(maxTreesPerChunk); t++){
// generates random locations for the X, Z positions\\
// the Y position is the height on the terrain gain with the X, Z coordinates \\
float TreeX = random.nextInt((int) (Settings.TERRAIN_VERTEX_COUNT + Settings.TERRAIN_SIZE)) + terrain.getX();
float TreeZ = random.nextInt((int) (Settings.TERRAIN_VERTEX_COUNT + Settings.TERRAIN_SIZE)) + terrain.getZ();
float TreeY = terrain.getTerrainHeightAtSpot(TreeX, TreeZ);
// creates a tree entity with the previous generated positions \\
Entity tree = new Entity(TreeStaticModel, new Vector3f(TreeX, TreeY, TreeZ), 0, random.nextInt(360), 0, 1);
// checks if the tree is on land \\
if(!(tree.getPosition().y <= -17)){
trees.add(tree);
}
}
Result:
First of all take a look at my:
simple C++ Island generator
as you can see you can compute Biomes from elevation, slope, etc... more sophisticated generators create a Voronoi map dividing your map into Biomes regions assigning randomly (with some rules) biome types based on neighbors already assigned...
Back to your question you should place your trees more dense around some position instead of uniformly cover large area with sparse trees... So you need slightly different kind of randomness distribution (like gauss). See the legendary:
Understanding “randomness”
on how to get a different distribution from uniform one...
So what you should do is get few random locations that would be covering your region shape uniformly. And then generate trees with density dependent on minimal distance to these points. The smaller distance the dense trees placement.
What are you looking for is a low-discrepancy-sequence to generate random numbers. The generated numbers are not truely random, but rather uniformly distributed. This distinguishes them from random number generators, which do not automatically produce uniformly distributed numbers.
One example of such a sequence would be the Halton Sequence, and Apache Commons also has an implementation which you can use.
double[] nextVector = generator.nextVector();
In your case, using two dimensions, the resulting array also has two entries. What you still need to do is to translate the points into your local coordinates by adding the the central point of the square where you want to place the forest to each generated vector. Also, to increase the gap between points, you should consider scaling the vectors.
Related
I have a 2D array of size n representing n number of points in the 3D space, position[][] for XYZ (e.g. position[0][0] is X, position[0][1] is Y, and position[0][2] is Z coordinate of point 0.
What I need to do is to do clustering on the points, so to have n/k number of clusters of size k so that each cluster consists of the k closest points in the 3D space. For instance, if n=100 and k=5, I want to have 20 clusters of 5 points which are the closest neighbors in space.
How can I achieve that? (I need pseudo-code. For snippets preferably in Java)
What I was doing so far was a simple sorting based on each component. But this does NOT give me necessarily the closest neighbors.
Sort based on X (position[0][0])
Then sort based on Y (position[0][1])
Then sort based on Z (position[0][2])
for (int i=0; i<position.length; i++){
for (int j=i+1; j<position.length; j++){
if(position[i][0] > position[i+1][0]){
swap (position[i+1][0], position[i][0]);
}
}
}
// and do this for position[i][1] (i.e. Y) and then position[i+2][2] (i.e. Z)
I believe my question slightly differs from the Nearest neighbor search with kd-trees because neighbors in each iteration should not overlap with others. I guess we might need to use it as a component, but how, that's the question.
At start you do not have a octree but list of points instead like:
float position[n][3];
So to ease up the clustering and octree creation you can use 3D point density map. It is similar to creating histogram:
compute bounding box of your points O(n)
so process all points and determine min and max coordinates.
create density map O(max(m^3,n))
So divide used space (bbox) into some 3D voxel grid (use resolution you want/need) do a density map like:
int map[m][m][m]`
And clear it with zero.
for (int x=0;x<m;x++)
for (int y=0;y<m;y++)
for (int z=0;z<m;z++)
map[x][y][z]=0;
Then process all points determine its cell position from x,y,z and increment it.
for (int i=0;i<n;i++)
{
int x=(m-1)*(position[i][0]-xmin)/(xmax-xmin);
int y=(m-1)*(position[i][1]-ymin)/(ymax-ymin);
int z=(m-1)*(position[i][2]-zmin)/(zmax-zmin);
map[x][y][z]++;
// here you can add point i into octree belonging to leaf representing this cell
}
That will give you low res density map. The higher number in cell map[x][y][z] the more points are in it which means a cluster is there and you can also move point to that cluster in your octree.
This can be recursively repeated for cells that have enough points. To make your octree create density map 2x2x2 and recursively split each cell until its count is lesser then threshold or cell size is too small.
For more info see similar QAs
Finding holes in 2d point sets? for the density map
Effective gif/image color quantization? for the clustering
What you what is not Clustering. From what you said, I think you want to divided your N points into N/k groups, with each group have k points, while keeping the points in each cluster are closest in the 3D space.
Think an easy example, if you want to do the same thing one one dimension, that is, just sort the numbers, and the first k points into cluster 1, the second k points into cluster 2, and so on.
Then return the 3D space problem, the answer is the same. Just first find the point with minimum x-axis, y-axis and z-axis, altogether with its closest k-1 points into Cluster 1. Then for the lest points, find the minimum x-axis, y-axis and z-axis points, and k-1 closest points not clustered into Cluster 2, and so on.
Above process will get your results, but that maybe not meaningful in practice, maybe cluster algorithms such as k-means could help you.
I work on a project, for this project I need to generate a square random invertible matrix.
I found out how to generate a square random matrix, still I want to be sure that this is an invertible one, without having to compute the determinant or to generate this matrix multiple times, can you please give me a tip?
One way is to generate the SVD of the matrix. That is you generate 'random' (square) orthogonal matrices U and V, and a 'random' diagonal matrix S, and then compute
M = U*S*V'
Note that every matrix has an SVD
As long as none of the diagonal elements of S are 0, M will be invertible. Many routines that deal with invertible matrices are sensitive to the condition number of the matrix; errors tend to increase as the condition number gets larger. The condition number of M is the same as the condition numner of S which is the largest (by absolute value) diagonal element of S divided by the smallest (by absolute value). You may want to control this. One way is to generate the elements of S to be uniform in say [lo,hi] and then randomly set the sign.
One way to generate 'random' orthogonal matrices is to generate then as a product of 'random' Householder reflections, that is matrices of the form
R_v = 1 - 2*v*v'/(v'*v)
where v is a 'random' vector.
Every n by n orthogonal matrix can be written as a product of n Householder reflections.
All this is not as computationally severe as it at first might look. Due to the special form of the reflectors it is straightforward to write routines that compute
R_u*M and M*R_v'
in M using only n extra storage and being O( n * n)
So one scheme would be
Generate S
Repeat n times
Generate random non zero vector u
Update S to be R_u*S
Generate random non zero vector v
Update S to be S*R_v'
An LU decomposition might work.
Generate two matrices, L, which is lower triangular with all entries above the main diagonal zero and, U, an upper triangular matrix with entries below the main diagonal zero. Then form a matrix A=LU.
The determinant of either L or U is just the product of entries down the main diagonal so you just need to ensure none of these are zero. The determinant of A is the product of the two determinants.
I've been working on a project and I need to be able to return a point in a square that acts kind of like a bulls-eye. I wanted to make it return a point that would follow a Gaussian distribution, meaning after a lot of generated results we would see the majority of the points generated near the center and the number would diminish as it goes towards the outer limits of the square. What would be the best way to go about this?
I have a method as seen here:
public static Point randomPoint(final Random random, final Point center,
final double sd) {
Point p = null;
return p;
}
But I am really stuck on where to go from here. With general numbers, a random gaussian number would just use a min and a max with a mean and standard deviation. would I do something similar here but do the min and max for both x and y?
To generate a symmetric 2d Gaussian distribution, you actually only have to generate 2 separate Gaussian numbers and take them as x and y, like this:
new Point(center.getX()+random.nextGaussian()*sd,
center.getY()+random.nextGaussian()*sd);
Note however that mean (the center) and deviation (I assume 'sd' in your example) does not equal min/max. It basically means that roughly 2/3 of all points will be less then 'sd' far from the center, roughly 95% will be at most '2*sd' far. However there is a non-zero probability for all points, however far.
This means, you might want to 'crop' the points to the rectangle of your interest. Note however, there are two approaches to do this:
If a point is outside the rectangle just put it on the border (aka. do min/max checking and take min/max if it's out of bounds)
Repeat the generation if point is outside of bounds
The first one will potentially deform your distribution, as it will be more likely that a point is on exactly the border than it should be. The second one costs a bit more processing, however it will preserve the distribution.
I've run into a problem where I have to be able to generate a set of randomly chosen numbers of a multivariate normal distribution with mean 0 and a given 3*3 variance-covariance matrix in Java.
Is there an easy way as to do this?
1) Use a library implementation, as suggested by Dima.
Or, if you really feel a burning need to do this yourself:
2) Assuming you want to generate normals with a mean vector M and variance/covariance matrix V, perform Cholesky Decomposition on V to come up with lower triangular matrix L such that V=LLt (where the superscript t indicates transpose). Generate a vector Z of three independent standard normals (using Random.nextGaussian() to get the individual elements). Then LZ + M will have the desired multivariate normal distribution.
Apache Commons has what you are looking for:
MultivariateNormalDistribution mnd = new MultivariateNormalDistribution(means, covariances);
double vals[] = mnd.sample();
this is my first question on these forums : )
I'm writing a coordinate class in Java for a spatial octree voxel system. These coordinates are not floating point coordinates, they are 4D integer indexes into the octree (3 normal dimensions X, Y, Z, and a forth for depth into the tree). The first 3 values are all shorts, the last dimension is a byte. In actual use right now only the first 11 bits of the shorts are used and only 3 bits of the byte, but this could be subject to change.
Now I'm trying to write a 'good' hash function for this class. The problem I'm wrestling with is that the coordinates are often going to be used in highly spatial coherent situations (hope I'm using the right terminology there). What I mean is that often times a coordinate will be hashed along with its immediately adjacent neighbors and other nearby coordinates.
Is there an effective practice to cause these 'near to each other' coordinates to produce significantly different hashcodes?
You are in luck: there is a way to get decent co-ordinate encodings with high spatial coherence using something called a Z-order curve.
The trick is to interleave the bits of the different co-ordinate components. So if you have 3 8-bit co-ordinates like:
[XXXXXXXX, YYYYYYYY, ZZZZZZZZ]
Then the z-curve encoded value would be a single 24-bit value:
XYZXYZXYZXYZXYZXYZXYZXYZ
You can extend to larger numbers of bits or co-ordinates as required.
This encoding works because co-ordinates which are close in space will have differences mainly in the lower order bits. So by interleaving the co-ordinates, you get the differences focused in the lower-order bits of the encoded value.
An extra interesting property is that the lower bits describe co-ordinates within cubes of space. So the lowest 3 bit address position with 2x2x2 cubes, the lowest 6 bits address position within 4*4*4 cubes, the lowest 9 bits position within 8*8*8 cubes etc. So this is actually a pretty ideal system for addressing co-ordinates within an octree.
"Significantly different" really depends on what you're doing with the hash code afterwards. In some cases it will then be subject to a round-robin bucket pick by taking the hash % size where size is the size of the hash map you're using, for example. Obviously that will change over time. I'd usually use something like:
int hash = 23;
hash = hash * 31 + x;
hash = hash * 31 + y;
hash = hash * 31 + z;
hash = hash * 31 + depth;
return hash;
(This is cribbed from Effective Java, basically.) Obviously it means that (x1, y1, z1) and (x1 + 1, y1 - 31, z1) would have the same hash code, but if you're mostly worried about very near neighbours it shouldn't be a problem.
EDIT: mikera's answer is likely to work better but be more complicated to code. I would personally try this very simple approach first, and see whether it's good enough for your actual use cases. Use progressively more effective but complicated approaches until you find one which is good enough.