I am using Unity c#, and I am coding something that relies on Perlin noise to determine a random number between 0 and 1. I would like to implement a feature in my code that allows the user to define a specific pre-determined seed number to use for this, but I am not sure if the Perlin noise function actually uses the same random seed as the Random class does.
For example; if I want to generate Perlin noise using Mathf.PerlinNoise() - will it always be the same if I always set the RNG seed priory, using the same number?
minimal code example:
Random.InitState(4815162342);
float _randomSample = Mathf.PerlinNoise(yada yada yada);
I would like to use this for a Minecraft-like system of generating a procedural game world and having a way for the player to choose a seed would be great. in that code example, the player's chosen seed was the numbers from the TV show "Lost". (4815162342)
The two are not related!
The only thing that Random.InitState changes is the way how e.g. Random.Range or Random.value work.
Without using it it would simply use values based on the system time instead.
Mathf.PerlinNoise is not connected to that. You can actually try different seeds and always see the same perlin result. This is actually stated in the API
The same coordinates will always return the same sample value but the plane is essentially infinite so it is easy to avoid repetition by choosing a random area to sample from.
They already give you a hint how to solve your problem: Use a different offset!
Now here comes your seed into play: Simply choose a random offset based on the seed -> random but always equal for the same seed!
Random.InitState(4815162342);
var randomOffsetX = Random.value;
var rabdomOffsetY = Random.value;
var values = new float[25];
for(var x = 0; x < 5; x++)
{
for(var y = 0; y < 5; y++)
{
values[x*5 + y] = Mathf.PerlinNoise(x + randomOffsetX, y + randomOffsetY);
}
}
This should give you 25 random values (between 0 and 1). But they should be equal for every time you use the same seed.
If you actually don't need the noise pattern but only one single value basically you could achieve the same thing simply using
Random.InitState(4815162342);
var value = Random.Range(0f, 1f);
Related
I'm reading data from a sensor. The sensor give an array of points (x,y). But as you can see in the image, there is a lot of noise:
.
I need to clean the data in a way that the data filtered, give a few points . Using something like Median,adjacent averaging, mean of the xy points or an algorithm that removes the noise. I know that there are a bunch of libraries in Python that make the work automatically. All the auto libraries that I found are base on image analysis and I think they do not work for this case because this is different, these are points (x,y) in a dataset.
point-cloud noise cleaned:
PD: I wanted to do the median of the points but i got confused when i tried with an bidimensional array (this mean ListOfPoints[[x,y],[x,y],[x,y],[x,y],[x,y],[x,y]]) I didn't know how to make that calculation with for or while to iterate and make the calc. I prefer C#, but if there is a solution in other language without libraries, I would be open to it.
One of the methods you can use is k_means algorithm. This picture briefly explains this algorithm k_means
This link fully explains the k_means algorithm. Also, how to create a loop on the input data. I don't think any additional explanation is needed k_means algorithm
K_menans algorithm is very simple and you will understand it with the first Google search
You could try doing a weighted average of the Y-value at sampled X-positions. Something like this:
List<Point2> filtered_points = new List<Point2>();
for (int x = xmin; x <= xmax; x++)
{
double weight_sum = 0;
List<double> weights = new List<double>();
foreach (Point2 p in point_list)
{
double w = 1.0/((p.x - x)*(p.x - x) + 1e-3);
weights.Add(w);
weight_sum += w;
}
double y = 0;
for (int i = 0; i < point_list.Count; i++)
{
y += weights[i]*point_list[i].y / weight_sum;
}
filtered_points.Add(new Point2(x, y));
}
You would probably need to tune the weights to get nice results. Also, in the example I am using a quadratic decay, but other weighting functions can be used (linear decay, gaussian function...)
This question already has answers here:
Generating a list of random numbers, summing to 1
(12 answers)
Closed 2 years ago.
I am making a space game with planets that are randomly generated and I need their atmospheres to be made up of random amounts of different elements. So the thing is that I want the elements to be percentages of the complete atmosphere, an example: oxygen = 30, nitrogen = 20, carbondioxide = 50, hydrogen = 0. All these values should be completely randomized and the sum of them all has to be 100.
I basically want to fill a container to the top with random amounts of set elements, but I don't know how to randomize all of the variables and end up with a fixed sum.
This is my first time submitting anything to StackOverflow so please let me know if there is anything I need to clarify, I've been stuck on this issue for so long without finding any answers so I would appreciate any help, thanks :)
(I am using c# in unity in case that makes a difference)
Well, you could think of it from the other perspective, and generate random values for each element, then use their total as 100%.
For instance...
var rnd = New Random()
ChecmicalsInAir = 9;
Hydrogen = rnd.Next();
Oxygen = rnd.Next();
...
TotalAtmos = (Hydrogen + Oxygen + ...);
Yes - as pointed out by canton7, below:
Dividing the chemical by TotalAtmos will give you the percentage of atmosphere.
Just to add a little more to this answer, you may also wish to use a Dictionary to store the information, rather than simple variables; that way you can include different gases in the atmosphere, as not all planets may have oxygen or nitrogen, this could add different bonuses or penalties, but remains a straightforward process for calculating percentages.
Questions like "how would you design this..." are better suited for Game Development. Those questions tend to get downvoted here a lot.
Here's one way you could do it.
int elementCount = 3; // set to the number of elements you have
List<float> elementPercents = new List<float>();
// Assign an initial value between 0 and 1 to each element, and set totalWeight
// to the sum of all those values. Note that this lets you have 0 for an element.
// If you don't want 0 for an element, adjust the Random.Range
float totalWeight = 0;
for (int i = 0; i < elementCount; i++)
{
elementPercents.Add(UnityEngine.Random.Range(0f, 1f));
totalWeight += elementPercents[i];
}
// Set the percent of each element to its proportion of the total weight.
// For example, if Oxygen = 0.1 and Hydrogen = 0.2 and Nitrogen = 0.3 from the above statement,
// then Oxygen's percent = 0.1 / (0.1 + 0.2 + 0.3) = 0.167
for (int i = 0; i < elementCount; i++)
{
elementPercents[i] /= totalWeight;
}
// Assign the percents to each element according to your requirements, for example
float hydrogen = elementPercents[0];
float nitrogen = elementPercents[1];
float oxygen = elementPercents[2];
I am making a program in C# that creates a list of tree objects that have graphics that display them all in a grid like fashion. After creating them I will have it to where each individual tree is moveed a random distance between -10 and 10 over the x and y axis; this will hopefully produce a look of scattered trees. I'm still new to C# basically.
My main problems are:
I'm not sure if it's possible to generate a number between -10 and 10 with my method
int randX = RandomClass.Next(-10, 10);
When I "skew" (skew is a loose term that I used to mean "move" in this context, its nothing literal) each tree's position, it seems as though I am applying the save amount of vertical and horizontal movement to many trees and not to one single tree individually.
public void SkewTrees()
{
if (skewed == false)
{
Vector2 emptyVector = Vector2.Zero;
int randX = RandomClass.Next(0, 100);
int randY = RandomClass.Next(0, 100);
Vector2 randSkew = new Vector2(randX , randY);
position=new Vector2(position.X+randSkew.X, position.Y+randSkew.Y);
skewed = true;
}
}
Full Code with link to actual output:
http://pastebin.com/zZ246t7U
For the random between -10 to 10, try something this way :
int rand = RandomClass.Next(1, 10) - RandomClass.Next(1, 10);
Or
int rand = RandomClass.Next(0, 20) - 10;
Or
int rand = RandomClass.Next(-10, 10);
Works too.
The Random-class produces a deterministic and reproducible sequence of numbers. It takes its seed from Environment.TickCount which changes every 15ms approximately. Therefore every instance of Random that you construct within such a 15ms time interval will produce exactly the same numbers.
In order to fix your code you need to ensure that you either use a good seed value or reuse a single Random class.
I recommend that you create a static variable with a single Random instance. Your entire program can reuse this variable.
I have recently used Visual Basic .Net to write a particle system which emits particles with random velocities in the x and y direction and is affected by gravity. I switched to C# .Net and used the XNA Game Studio which makes the graphics handling much more convenient than GDI+.
The problem I have with C# is that the random numbers are not "random enough". My particle system has 2500 particles but you can clearly see that the particles are distributed in a grid-like fashion about 100 pixels apart and I did not have that problem with Visual Basic's Rnd() function.
What does Visual Basic do which C# does not, and how can I get the same results in C#?
I have tried to re-initialise my random numbers at different stages of the game loop but I end up either with my particles staying at one position or emitting just in a constant stream in one direction.
This is my C# code: LoadContent is called first thing after the program has started. I'm using the millisecond as a seed just so that I start each time with a different configuration.
The next time I re-seed is after all the calculations are done on the system just before rendering. The other alternative I tried is to re-seed after every 100 particles have been calculated but with no difference.
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
mousePos = Content.Load<Texture2D>("Point");
spriteTex = Content.Load<Texture2D >("Point");
rnd = new Random(a.Millisecond);
for (int i = 0; i < spritePos .Length; i++)
{
newPos[i] = new Vector2(800, 450);
spritePos[i] = newPos[i] ;
Scale[i] = rnd.Next(100,500);
renderCol[i] = new Color(rnd.Next(255), rnd.Next(255), rnd.Next(255), 1);
spriteVelocity[i] = new Vector2((rnd.Next(2000)-1000)/100, -rnd.Next(500,1500)/100);
Life[i] = rnd.Next(60);
Rotate[i] = (rnd.Next(1000)-500) * 0.001f;
RotateSpeed[i] = (rnd.Next(1000)-500) * 0.0001f;
}
}
This is my VB code, the only place where I use the rnd function:
For i = x To x + 1000
ptc(i) = New particle(New Vector((Rnd() * 200) - 200 * Rnd(), Rnd() * -100 - 200 * Rnd() - 200), New Vector(e.X, e.Y), 500, Color.FromArgb(Rnd() * 255, 255, 0))
x += 1
Next
In my VB code there is no place where I call the randomize function, I have noticed that my particles have the same pattern-like behaviour if I do. Excuse all the strange arithmetic, it's all just experimentation.
Ok, what you do to fix it Charl, is to create a single Random object (which you are) with no seed, and use it over and over again. So something like:
const double max = 1000.0;
Random rand = new Random(); // Like mentioned, don't provide a seed, .NET already picks a great seed for you
for(int iParticle = 0; iParticle < 2500; iParticle++)
{
double x = rand.NextDouble() * max; // Will generate a random number between 0 and max
double y = rand.NextDouble() * max;
}
To get a random floating point value (float or double) between a lower and upper bound, you can use something like:
double x = (rand.NextDouble() * (max - min)) + min;
EDIT: And make sure to use double or float. Ints are whole numbers only, doubles and floats can store real numbers and is probably what VB was using.
If you had posted some code we would probably have been able to point out where you are creating a new Random() object for each call .
Like in, for example, Random number in a loop
After seeing the code,
are you aware that (rnd.Next(2000)-1000)/100 is an integer only expression? The result will be converted to float but always end in ##.0.
In VB I / J yields a double.
Random class ensures pseudo-randomness, if that is what you are using. Have a look at RNGCryptoServiceProvider.
I'm currently implementing a software that measures certain values over time. The user may choose to measure the value 100 times over a duration of 28 days. (Just to give an example)
Linear distribution is not a problem, but I am currently trying to get a logarithmical distribution of the points over the time span.
The straight-forward implementation would be to iterate over the points and thus I'll need an exponential function. (I've gotten this far!)
My current algorithm (C#) is as follows:
long tRelativeLocation = 0;
double tValue;
double tBase = PhaseTimeSpan.Ticks;
int tLastPointMinute = 0;
TimeSpan tSpan;
for (int i = 0; i < NumberOfPoints; i++)
{
tValue = Math.Log(i + 1, NumberOfPoints);
tValue = Math.Pow(tBase, tValue);
tRelativeLocation = (long)tValue;
tSpan = new TimeSpan(tRelativeLocation);
tCurrentPoint = new DefaultMeasuringPointTemplate(tRelativeLocation);
tPoints.Add(tCurrentPoint);
}
this gives me a rather "good" result for 28 days and 100 points.
The first 11 points are all at 0 seconds,
12th point at 1 sec,
20th at 50 sec,
50th at 390 min,
95th at 28605 mins
99 th at 37697 mins (which makes 43 hours to the last point)
My question is:
Does anybody out there have a good idea how to get the first 20-30 points further apart from each other, maybe getting the last 20-30 a bit closer together?
I understand that I will eventually have to add some algorithm that sets the first points apart by at least one minute or so, because I won't be able to get that kind of behaviour into a strictly mathematical algorithm.
Something like this:
if (((int)tSpan.TotalMinutes) <= tLastPointMinute)
{
tSpan = new TimeSpan((tLastPointMinute +1) * 600000000L);
tRelativeLocation = tSpan.Ticks;
tLastPointMinute = (int)tSpan.TotalMinutes;
}
However, I'd like to get a slightly better distribution overall.
Any cool ideas from you math cracks out there would be greatly appreciated!
From a practical point of view, the log function squeezes your time point near the origin already. A power function squeezes them even more. How about simple multiplication?
tValue = Math.Log(i + 1, NumberOfPoints);
tValue = tBase * tValue;
Another way to flatten the curve is start farther from the origin.
for (int i = 0; i < NumberOfPoints; i++)
{
tValue = Math.Log(i + 10, NumberOfPoints + 9);
The range of tvalue is still 0 to 1.
How about this to have a minimum space of 1 second at the beginning?
double nextTick = 0;
for (int i = 0; i < NumberOfPoints; i++)
{
tValue = Math.Log(i + 1, NumberOfPoints);
tValue = Math.Pow(tBase, tValue);
if (tValue < nextTick) tValue = nextTick;
nextTick++;
The distribution curve you choose depends on what you're measuring.
A straight line, a sine wave, a polynomial or exponential curve may individually be the best distribution curve for a given set of measurements.
Once you've decided on the distribution curve, you calculate the missing data points by calculating the y value for any given time value (x value), using the mathematical formula of the curve.
As an example, for a straight line, all you need is one data point and the slope of the line. Let's say at time 0 the measured value is 10, and the measurement goes up by 2 every minute. The formula would by y = 2 * x + 10. if we wanted to calculate the measurement when x = 5 (minutes), the formula gives us a measurement of 20.
For a logarithmic curve, you'd use a logarithm formula. For simplicity, let's say that the actual measurements give us a formula of y = 2 ** x + 12; You plug in the time values (x values) you want to calculate, and calculate the measurements (y values).
Realize that you are introducing calculation errors by calculating data points instead of measuring. You should mark the calculated data points in some manner to help the person reading your graph differentiate them from actual measurements.
I am not exactly sure what you are trying to do, your code does not seem to match your example (it could be that I am screwing up the arithmetic). If you want your samples to have a minimum separation of 1 sec, and each point at a location of x times the last point (except for the first) then you want to find x such that x^(n - 1) = span. This is just x = exp(log(span) / (n - 1)). Then your points would be at x^i for(i = 0; i < n; i++)