So I have this application where I'm generating random offsets to plot a random shape on the canvas. This is how the code looks like for generating random offsets:
// generating 5 random offsets
for (int i = 0; i < points; i++) {
// width random ranges from 20% of width to 80% of width
double randomWidth =
Random().nextInt((width * .6).toInt()) + (width * .2);
// height random ranges from 20% of height to 80% of height
double randomHeight =
Random().nextInt((height * .6).toInt()) + (height * .2);
// adding the offset to the list
offsets.add(Offset(randomWidth, randomHeight));
}
// generating the lines polygon
canvas.drawPoints(ui.PointMode.polygon, offsets, paint);
This code seems to be working fine but there is an issue. Sometimes the points seems to be plotted very near to other points and sometimes on the other plotted line. What I want is to have all the points maintain some distance from each other so that they are not close to each other. These are the plots that I don't want:
If I have the following chart in Flutter:
Where the green graph is a Path object with many lineTo segments, how do I find the y-coordinate for a point with a given x-coordinate?
As you can see in the image, there is a gray dotted line at a specific point on the x-axis and I want to draw a point where it intersects with the green graph.
Here is an example path:
final path = Path();
path.moveTo(0, 200);
path.lineTo(10, 210);
path.lineTo(30, 190);
path.lineTo(55, 150);
path.lineTo(80, 205);
path.lineTo(100, 0);
And I want to find the y-coordinate for the point at dx = 75.
The easiest way to achieve this for any path that only has a single point for every x (i.e. where there is only a single graph / line from left to right) is using the binary search algorithm.
You can then simply use the distance of the path, which is obtained using Path.computeMetrics, to perform binary search and find the offset via Path.getTangentForOffset:
const searchDx = 75;
const iterations = 12;
final pathMetric = path.computeMetrics().first;
final pathDistance = pathMetric.length;
late Offset closestOffset;
var closestDistance = pathDistance / 2;
for (var n = 1; n <= iterations; n++) {
closestOffset = pathMetric.getTangentForOffset(closestDistance)!.position;
if (closestOffset.dx == searchDx) break;
final change = pathDistance / pow(2, n);
if (closestOffset.dx < searchDx) {
closestDistance += change;
} else {
closestDistance -= change;
}
}
print(closestOffset); // Offset(75.0, 193.9)
Note that if you want to run significantly more iterations (which should not be necessary due to the nature of binary search), you should replace final change = pathDistance / pow(2, n); by a cheaper operation like storing the left and right points of your current search interval.
You can find the full working code as an example on Dartpad.
I have 2 long, lat points of a rectangle(bottom left and top right) and I want to divide this rectangle into smaller ones based on a base area (long and lat) I already have. I already know that I can't deal with long and lat as distance measured with meters and kilometres but degrees on an approximation of Earth's surface shape.
The points taken is extracted by leaflet with a 4326 SRID and so are the original points. I need the centre of the "smaller squares" or the long and lat coordinates.
For example, this is my base rectangle 24.639567,46.782406 24.641452,46.785413 and for the rectangle, I want to divide 24.584749,46.612782 24.603323,46.653809.
First, let's turn your two points into a leaflet bounds object:
const bounds - L.latLngBounds(point1, point2)
Now let's pick a sample interval, meaning how many sub-rectangles across the width and height of your bounds. For example, a sampling size of 10 would give 100 sub-rectangles (10 x 10), though if your sub-rectangles don't need the same aspect-ratio as your main bounds, you could choose two separate sampling intervals (one for x and one for y)
const samplingInterval = 10 // easy to change
To properly interpolate through your main bounds, we'll grab the corners of it, as well as the width in longitude degrees, and height in latitude degrees, called dLat and dLng (for delta):
const sw = bounds.getSouthWest();
const nw = bounds.getNorthWest();
const ne = bounds.getNorthEast();
const dLat = ne.lat - sw.lat;
const dLng = ne.lng - nw.lng;
Now we can build an array of new bounds extrapolated from the original:
let subBounds = [];
for (let i = 0; i < samplingInterval - 1; i++){
for (let j = 1; j < samplingInterval; j++){
const corner1 = [
sw.lat + (dLat * i) / samplingInterval,
sw.lng + (dLng * j) / samplingInterval
];
const corner2 = [
sw.lat + (dLat * (i + 1)) / samplingInterval,
sw.lng + (dLng * (j + 1)) / samplingInterval
];
subBounds.push(L.latLngBounds(corner1, corner2));
}
}
Now to get the centers of these bounds, you can call .getCenter() on them:
const centerPoints = subBounds.map(bounds => bounds.getCenter());
Working codesandbox
I have a voxel based game in development right now and I generate my world by using Simplex Noise so far. Now I want to generate some other structures like rivers, cities and other stuff, which can't be easily generated because I split my world (which is practically infinite) into chunks of 64x128x64. I already generated trees (the leaves can grow into neighbouring chunks), by generating the trees for a chunk, plus the trees for the 8 chunks surrounding it, so leaves wouldn't be missing. But if I go into higher dimensions that can get difficult, when I have to calculate one chunk, considering chunks in an radius of 16 other chunks.
Is there a way to do this a better way?
Depending on the desired complexity of the generated structure, you may find it useful to first generate it in a separate array, perhaps even a map (a location-to-contents dictionary, useful in case of high sparseness), and then transfer the structure to the world?
As for natural land features, you may want to google how fractals are used in landscape generation.
I know this thread is old and I suck at explaining, but I'll share my approach.
So for example 5x5x5 trees. What you want is for your noise function to return the same value for an area of 5x5 blocks, so that even outside of the chunk, you can still check if you should generate a tree or not.
// Here the returned value is different for every block
float value = simplexNoise(x * frequency, z * frequency) * amplitude;
// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;
And now we'll plant a tree. For this we need to check what x y z position this current block is relative to the tree's starting position, so we can know what part of the tree this block is.
if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
// Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
int startY = height(startX + 2, startZ + 2) + 1;
int relx = x - startX; // block pos relative to starting position
int relz = z - startZ;
for(int j = startY; j < startY + 5; j++) {
int rely = j - startY;
byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
tiles[i][j][k] = tile;
}
}
The tree 3d array here is almost like a "prefab" of the tree, which you can use to know what block to set at the position relative to the starting point. (God I don't know how to explain this, and having english as my fifth language doesn't help me either ;-; feel free to improve my answer or create a new one). I've implemented this in my engine, and it's totally working. The structures can be as big as you want, with no chunk pre loading needed. The one problem with this method is that the trees or structures will we spawned almost within a grid, but this can easily be solved with multiple octaves with different offsets.
So recap
for (int i = 0; i < 64; i++) {
for (int k = 0; k < 64; k++) {
int x = chunkPosToWorldPosX(i); // Get world position
int z = chunkPosToWorldPosZ(k);
// Here the returned value is different for every block
// float value = simplexNoise(x * frequency, z * frequency) * amplitude;
// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;
if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
// Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
int startY = height(startX + 2, startZ + 2) + 1;
int relx = x - startX; // block pos relative to starting position
int relz = z - startZ;
for(int j = startY; j < startY + 5; j++) {
int rely = j - startY;
byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
tiles[i][j][k] = tile;
}
}
}
}
So 'i' and 'k' are looping withing the chunk, and 'j' is looping inside the structure. This is pretty much how it should work.
And about the rivers, I personally haven't done it yet, and I'm not sure why you need to set the blocks around the chunk when generating them ( you could just use perlin worms and it would solve problem), but it's pretty much the same idea, and for your cities too.
I read something about this on a book and what they did in these cases was to make a finer division of chunks depending on the application, i.e.: if you are going to grow very big objects, it may be useful to have another separated logic division of, for example, 128x128x128, just for this specific application.
In essence, the data resides is in the same place, you just use different logical divisions.
To be honest, never did any voxel, so don't take my answer too serious, just throwing ideas. By the way, the book is game engine gems 1, they have a gem on voxel engines there.
About rivers, can't you just set a level for water and let rivers autogenerate in mountain-side-mountain ladders? To avoid placing water inside mountain caveats, you could perform a raycast up to check if it's free N blocks up.
Is there a way or tool to generate random GeoJSON polygons of specific size withing bounding box? Specifically I want to populate mongodb with a lot of random polygons and test specific functionality.
You could do it programmatically using the bounding box coordinates to generate the random bounding box coords for the rectangles.
For example, if your bounding box is [[100,100],[200,200]] you could do the following:
// generate a random width and height
// (e.g. with random numbers between 1 and 50)
var width = Math.floor(Math.random() * 50) + 1;
var height = Math.floor(Math.random() * 50) + 1;
// generate a random position that allows the rectangle to fit within the bounding box walls
// 100 is used in the calculation as 100 is the width and height of the example bounding box
var upperX = Math.floor(Math.random() * (100-width)) + 1;
var upperY = Math.floor(Math.random() * (100-height)) + 1;
var lowerX = upperX + width;
var lowerY = upperY + height;
var bounds = [[upperX, upperY], [lowerX, lowerY]];
// create rectangle
L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
// loop through above code some chosen number of times