amidstest/src/main/java/amidst/minetest/world/mapgen/ClimateHistogram.java

331 lines
25 KiB
Java

package amidst.minetest.world.mapgen;
import javax.vecmath.Point2d;
import java.util.Arrays;
import java.util.LongSummaryStatistics;
import amidst.logging.AmidstLogger;
/**
* This class uses pre-generated data, so can only provide histogram
* information for climate noise settings similar to Minetest's default settings.
*/
public class ClimateHistogram implements IHistogram2D {
private static final float DEFAULT_SCALE = 50;
private static final float DEFAULT_OFFSET = 50;
private static final float DEFAULT_BLEND_SCALE = 50;
private static final float DEFAULT_BLEND_OFFSET = 50;
float scaleAdj = 1;
float offsetAdj = 0;
double dataSampleCount = 4293525600d * 6; // data is sum of 6 full-world samples
int dataSampleOffset = 40; // the first value in sampledHistogram_Heat is for heat of -40
// Bins: 191, range: -40 to 150 (inclusive)
int[] sampledHistogram_Heat = new int[] {0, 0, 23, 896, 5273, 18130, 35423, 56932, 85873, 144492, 227887, 330382, 441791, 575273, 785758, 1104880, 1514226, 2008173, 2580628, 3270470, 4070347, 5010230, 6233724, 7665743, 9231443, 11032009, 13054672, 15159146, 17585779, 20431953, 23539132, 26777647, 30049708, 33634225, 37557763, 41702212, 46135583, 50960488, 56066254, 61483250, 67471538, 74036663, 81075916, 88392031, 95671758, 103028198, 110423079, 118133581, 126230683, 134525547, 143089365, 151816479, 160572896, 169173433, 177480719, 185603411, 193673745, 201819880, 210125434, 218400248, 226576667, 234675120, 242660227, 250393165, 257641763, 264310278, 271052198, 277926795, 284991256, 291581211, 297501193, 303087896, 308619131, 313777446, 318058063, 322212943, 326758548, 331475102, 335722459, 338714730, 340704226, 342259956, 344228530, 346336570, 348439520, 350388503, 352166050, 353596154, 355021883, 355344601, 354627956, 353920683, 353523974, 353330547, 353024545, 352813804, 352102001, 350967293, 349073000, 346178826, 343181131, 340158957, 336577363, 332492808, 328136486, 323579081, 319083180, 314922134, 310380729, 305265626, 299550379, 293823815, 287790026, 282008407, 276140320, 269559012, 262131740, 254605986, 246951793, 239251561, 230994017, 222093705, 213071865, 204219912, 195608147, 187251811, 178964522, 170779498, 162561496, 154205050, 145761473, 137219761, 128986832, 121138771, 113558434, 106120928, 98743038, 91314126, 83938278, 77103922, 70855499, 64921287, 59244041, 53844544, 48822704, 43909928, 39348668, 35160583, 31266663, 27623387, 24258537, 21091241, 18212811, 15617700, 13237251, 11059423, 9228541, 7789154, 6607381, 5466830, 4340725, 3364753, 2610074, 2004609, 1486276, 1069920, 750199, 518992, 357847, 267761, 204042, 135284, 70635, 31506, 16563, 14437, 12363, 6219, 1714, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int[] sampledHistogram_Humidity = new int[] {0, 0, 31, 498, 2506, 4845, 8185, 21468, 59847, 122732, 193470, 286771, 438554, 610779, 784774, 1018080, 1351444, 1762206, 2271350, 2871968, 3617679, 4542319, 5722714, 7087672, 8612730, 10322878, 12252077, 14556399, 17083672, 19781372, 22738287, 25903300, 29414149, 33280369, 37456084, 41913668, 46847975, 52063820, 57365491, 62720169, 68287651, 74188447, 80622299, 87458209, 94297778, 101540429, 109407209, 117764134, 126033776, 134106841, 142075245, 150160062, 158481411, 167046905, 175806629, 184285718, 192691920, 201123443, 209651797, 218157100, 226149374, 234230435, 242366234, 249849182, 257017437, 264178652, 271211835, 277958877, 284189278, 290172767, 296085575, 301995199, 307977042, 313261332, 317868477, 322201082, 326388271, 330472979, 334532622, 338385357, 341846286, 344688035, 346974698, 349233925, 351053588, 352480803, 353676423, 354853005, 355571248, 355946018, 356187678, 355726165, 354284344, 352881704, 351909613, 350696269, 348847862, 346809607, 345187333, 343247921, 340859439, 338049103, 335025305, 331513640, 327718695, 323952706, 320112005, 316183516, 311617470, 306291881, 300848532, 295309226, 289332030, 282903833, 276250749, 269695133, 262942145, 255893757, 248411772, 240532829, 232446716, 224124693, 215607785, 206986511, 198415028, 190161781, 182277837, 174044450, 165348412, 156451475, 147683121, 139285547, 131231683, 123268099, 115122762, 107128906, 99350517, 91804617, 84384451, 77313619, 70743606, 64517248, 58541831, 52903662, 47555609, 42575213, 38003184, 33839429, 30012843, 26495082, 23211478, 20191059, 17507769, 14994437, 12727017, 10648031, 8847912, 7389304, 6184783, 5132563, 4108008, 3175730, 2394676, 1814862, 1395580, 1096984, 856680, 630982, 413928, 233980, 123637, 63560, 37317, 19663, 8361, 1825, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// See the code in the constructor if you wish to recalculate frequencyAtPercentileTable
/** A pre-calculation table for percentiles 1 to 100, in 1 percentile increments */
double[] frequencyAtPercentileTable = new double[] {4.288849623506293E-6, 7.849271137128854E-6, 1.0935481111330147E-5, 1.4125178764733622E-5, 1.710500033323479E-5, 1.9993831214913553E-5, 2.2662552870656077E-5, 2.534060066104869E-5, 2.802187248207058E-5, 3.080643823350056E-5, 3.33861856758062E-5, 3.6068277994214394E-5, 3.862936637606668E-5, 4.095044456557262E-5, 4.3636595467822336E-5, 4.607358640977918E-5, 4.810443669853268E-5, 5.0837165362693565E-5, 5.296404267788116E-5, 5.5325852990715865E-5, 5.7679007766327825E-5, 5.983630193800486E-5, 6.235772026254966E-5, 6.430623785962591E-5, 6.669710263491633E-5, 6.855912078302344E-5, 7.113548845931662E-5, 7.295088808887063E-5, 7.542181961574365E-5, 7.713810513240832E-5, 7.941207236464512E-5, 8.162108120760272E-5, 8.386222016118836E-5, 8.569039655815985E-5, 8.746946795713887E-5, 8.971102202243205E-5, 9.113804797595727E-5, 9.331997156194227E-5, 9.538586351908653E-5, 9.734525496179133E-5, 9.898022955022616E-5, 1.0102734313517474E-4, 1.0297431176541194E-4, 1.0459706284256709E-4, 1.0668836696809265E-4, 1.0855615168551473E-4, 1.1007621103277895E-4, 1.1237809589729694E-4, 1.1365508528516895E-4, 1.1581159959767767E-4, 1.1773346682435759E-4, 1.1928685427735908E-4, 1.2109096765312022E-4, 1.2266224460033028E-4, 1.2460344924158565E-4, 1.2639392703246802E-4, 1.2792145643612953E-4, 1.2983742624993134E-4, 1.3126086274433714E-4, 1.3318981239435993E-4, 1.3466113206470656E-4, 1.3628693214058266E-4, 1.3771262506116956E-4, 1.3927642904768147E-4, 1.4088517346529805E-4, 1.424651674401106E-4, 1.4415914818743247E-4, 1.4584085961605385E-4, 1.4707407523891278E-4, 1.48740812877974E-4, 1.4998644757789717E-4, 1.5182775373866035E-4, 1.5312561398223614E-4, 1.5476944096761824E-4, 1.564096559253218E-4, 1.5747584559976162E-4, 1.592317541086737E-4, 1.6055180720478152E-4, 1.6209298336552515E-4, 1.6335932626023207E-4, 1.6501788334796102E-4, 1.6627703968019814E-4, 1.6756546371099305E-4, 1.6888984543785755E-4, 1.7039589568960874E-4, 1.717707149296396E-4, 1.7299179342349547E-4, 1.744319494242184E-4, 1.7608213347237582E-4, 1.7744060109174724E-4, 1.7877565932783E-4, 1.8007180142527902E-4, 1.8136873249310507E-4, 1.8273003575625964E-4, 1.8385915609410723E-4, 1.8507326100357174E-4, 1.8627491892689703E-4, 1.8740872113945042E-4, 1.8879158216656317E-4, 1.9033705137062054E-4};
/** A pre-calculation table for percentiles 0 to 0.99 in 0.01 percentile increments */
double[] frequencyAtPerdimileTable = new double[] {0.0, 7.906411381395254E-8, 1.4281584607842585E-7, 2.0367198773824541E-7, 2.579481623074614E-7, 3.103739993944631E-7, 3.663211869054443E-7, 4.169483003809781E-7, 4.635227228946929E-7, 5.288508873488246E-7, 5.686991889665327E-7, 6.204826202407989E-7, 6.812762234709958E-7, 7.263347560698961E-7, 7.657426809358803E-7, 8.193734165334142E-7, 8.656717598377384E-7, 9.267166497130238E-7, 9.687699186503285E-7, 1.0100613846028922E-6, 1.040421908192894E-6, 1.0981246626722591E-6, 1.1626975068704957E-6, 1.2072828789096895E-6, 1.245628837090483E-6, 1.2925330631771625E-6, 1.3136720582621303E-6, 1.3539419032545604E-6, 1.4261585444809766E-6, 1.4613406586174258E-6, 1.5325176657436087E-6, 1.5737994074503633E-6, 1.6102602927831794E-6, 1.6548696775342068E-6, 1.6814410653583067E-6, 1.7109022657620896E-6, 1.739729245372117E-6, 1.818909640506737E-6, 1.860652162367776E-6, 1.918256413753668E-6, 1.950305933579097E-6, 2.0142046144063015E-6, 2.0414075345970236E-6, 2.078387302258539E-6, 2.1271279829810187E-6, 2.149899817465148E-6, 2.1755325291439493E-6, 2.204795837375724E-6, 2.2850671080176522E-6, 2.32281076679128E-6, 2.373852151766557E-6, 2.420014414654376E-6, 2.4519443333869577E-6, 2.4886672811746097E-6, 2.5482357788527957E-6, 2.5826040900445513E-6, 2.62377928182969E-6, 2.6443912878365593E-6, 2.6742844225227714E-6, 2.6967536393142994E-6, 2.729072454192572E-6, 2.7697985570250263E-6, 2.8357136937141744E-6, 2.886882959408015E-6, 2.9324497121704535E-6, 2.973268481768577E-6, 3.010129601199772E-6, 3.0440263924820617E-6, 3.097221433350364E-6, 3.153942913939244E-6, 3.1693172695523055E-6, 3.208017787514919E-6, 3.2466586058243742E-6, 3.2873911331250026E-6, 3.300640985971264E-6, 3.3135005090680394E-6, 3.360507790578272E-6, 3.4192720091466502E-6, 3.4414606133149838E-6, 3.480699054050278E-6, 3.5502316470557827E-6, 3.608426792734956E-6, 3.6396339028551223E-6, 3.6863827940008945E-6, 3.7040534454740007E-6, 3.7410242395545514E-6, 3.7825944022123806E-6, 3.847435398836006E-6, 3.873875563025558E-6, 3.9031983332453956E-6, 3.931204415840417E-6, 3.9598830516054155E-6, 3.975995856789808E-6, 3.998365240336164E-6, 4.039172655337482E-6, 4.0632862055249795E-6, 4.0990893986543585E-6, 4.183983009230883E-6, 4.216663091722728E-6, 4.245830038292284E-6};
// See the code in the constructor if you wish to recalculate processedHistogram_Heat
long[] processedHistogram_Heat = new long[] {0, 153, 1768, 7613, 20266, 39237, 68532, 129569, 253672, 466068, 749036, 1118894, 1652120, 2336026, 3177411, 4289864, 5747526, 7589850, 9856728, 12682921, 16136759, 20151942, 24748602, 29931873, 35920626, 43062341, 51271017, 60327682, 70390031, 81495625, 93747434, 106799416, 120743363, 135914606, 152365699, 170101021, 189361871, 209772514, 231217617, 253641954, 277358294, 302642651, 330020944, 358968983, 388063091, 417818461, 448511484, 480304585, 512482974, 545137696, 578609204, 612633066, 646964215, 681044286, 714529707, 747302721, 780388840, 814149746, 848456881, 882775746, 916166774, 948689945, 980390026, 1010742090, 1039733085, 1067743075, 1094655102, 1120797912, 1146302590, 1170887019, 1193985679, 1216640602, 1238594372, 1258144428, 1275121725, 1291945812, 1309002000, 1325954529, 1341857749, 1355308147, 1366591082, 1376374738, 1385463561, 1393347395, 1400442971, 1406379379, 1410776631, 1414661410, 1418401449, 1420937467, 1421631268, 1420937467, 1418401449, 1414661410, 1410776631, 1406379379, 1400442971, 1393347395, 1385463561, 1376374738, 1366591082, 1355308147, 1341857749, 1325954529, 1309002000, 1291945812, 1275121725, 1258144428, 1238594372, 1216640602, 1193985679, 1170887019, 1146302590, 1120797912, 1094655102, 1067743075, 1039733085, 1010742090, 980390026, 948689945, 916166774, 882775746, 848456881, 814149746, 780388840, 747302721, 714529707, 681044286, 646964215, 612633066, 578609204, 545137696, 512482974, 480304585, 448511484, 417818461, 388063091, 358968983, 330020944, 302642651, 277358294, 253641954, 231217617, 209772514, 189361871, 170101021, 152365699, 135914606, 120743363, 106799416, 93747434, 81495625, 70390031, 60327682, 51271017, 43062341, 35920626, 29931873, 24748602, 20151942, 16136759, 12682921, 9856728, 7589850, 5747526, 4289864, 3177411, 2336026, 1652120, 1118894, 749036, 466068, 253672, 129569, 68532, 39237, 20266, 7613, 1768, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
long[] processedHistogram_Humidity = processedHistogram_Heat;
double dataProcessedCount = dataSampleCount * 4; // we doubled the sample data by mirroring it horizontally, and doubled that by mirroring vertically
Point2d sampleMean = null;
public double FrequencyOfTemperature(float temperature) {
int index = Math.round((temperature / scaleAdj) + offsetAdj) + dataSampleOffset;
if (index >= 0 && index < processedHistogram_Heat.length) {
//return sampledHistogram_Heat[index] / dataSampleCount;
return processedHistogram_Heat[index] / dataProcessedCount;
} else {
// Our sampling range covers all non-zero values, so the answer to return is zero,
// however NaN should help highlight if range bugs are occurring elsewhere in the app.
return Double.NaN;
}
}
public double FrequencyOfHumidity(float humidity) {
int index = Math.round((humidity / scaleAdj) + offsetAdj) + dataSampleOffset;
if (index >= 0 && index < processedHistogram_Heat.length) {
//return sampledHistogram_Humidity[index] / dataSampleCount;
return processedHistogram_Heat[index] / dataProcessedCount;
} else {
// Our sampling range covers all non-zero values, so the answer to return is zero,
// however NaN should help highlight if range bugs are occurring elsewhere in the app.
return Double.NaN;
}
}
/**
* Returns a value between 0 and 1 which represents how frequently a
* block should have a climate of (temperature, humidity).
* (uses linear interpolation)
*/
@Override
public double frequencyOfOccurance(float temperature, float humidity) {
// Linearly-interpolate instead of rounding temperature and humidity
float temperature_floor = (float)Math.floor(temperature);
float humidity_floor = (float)Math.floor(humidity);
double freq_floor = FrequencyOfTemperature(temperature_floor);
double freq_ceil = FrequencyOfTemperature((float)Math.ceil(temperature));
if (!(freq_floor > 0 && freq_ceil > 0) && FrequencyOfTemperature(temperature) == 0) return 0; // Don't interpolate the frequency if it's a value that cannot ever happen (the first two checks are just an optimization to prevent unnecessarily invoking FrequencyOfTemperature)
double temperature_interp = freq_floor + (freq_ceil - freq_floor) * (temperature - temperature_floor);
freq_floor = FrequencyOfHumidity(humidity_floor);
freq_ceil = FrequencyOfHumidity((float)Math.ceil(humidity));
if (!(freq_floor > 0 && freq_ceil > 0) && FrequencyOfTemperature(humidity) == 0) return 0; // Don't interpolate the frequency if it's a value that cannot ever happen (the first two checks are just an optimization to prevent unnecessarily invoking FrequencyOfTemperature)
double humidity_interp = freq_floor + (freq_ceil - freq_floor) * (humidity - humidity_floor);
return temperature_interp * humidity_interp;
}
/**
* Returns the "FrequencyOfOccurance" value at which 'percentile' amount of
* samples will fall beneath.
* So if percentile was 10, then a value between 0 and 1 would be returned such
* that 10% of results from FrequencyOfOccurance() would fall below it.
*/
@Override
public double frequencyAtPercentile(double percentile) {
// use the lookup-table
if (percentile >= 0.995) {
return frequencyAtPercentileTable[(int)Math.round(Math.max(1, Math.min(100, percentile))) - 1];
} else {
return frequencyAtPerdimileTable[(int)Math.round(Math.max(0, Math.min(100, percentile * 100)))];
}
}
@Override
public Point2d getSampleMean() {
// We know the true mean of the noise, so use that.
if (sampleMean == null) sampleMean = new Point2d(DEFAULT_OFFSET + offsetAdj, DEFAULT_OFFSET + offsetAdj);
return sampleMean;
}
/**
* The data from the 3 octaves of Perlin noise plus 2 octaves blending is
* *not* of a Normal Distribution, and any math that assumes it is will fail.
* This function calculates what the the mean the standard deviation
* would be if it was a normal distribution.
* (Not used, but left in for reference)
*
* Spoiler: it's ~26 (perhaps exactly 26)
*/
private double getStandardDeviation(int[] histogram) {
// Work out the Mean (we actually know it should be 50)
double total = 0;
long sampleCount = 0;
for (int i = histogram.length - 1; i >= 0; i--) {
long sample = i - dataSampleOffset;
total += (sample * histogram[i]);
sampleCount += histogram[i];
}
double mean = total / (double)sampleCount;
// Then for each number: subtract the Mean and square the result
double squaredDifferenceTotal = 0;
for (int i = 0; i < histogram.length; i++) {
long sample = i - dataSampleOffset;
double squaredDifference = (sample - mean) * (sample - mean);
squaredDifferenceTotal += squaredDifference * histogram[i];
}
// Then work out the mean of those squared differences.
double meanOfSquaredDifference = squaredDifferenceTotal / ((double)sampleCount - 1); // -1 for Bessel's correction
// Take the square root of that and we are done!
return Math.sqrt(meanOfSquaredDifference);
}
/**
* Returns the percentage of sample locations/bins that occur at or below the given frequency_of_occurance
* @see PercentileAtFrequency_Processed
*/
private double PercentileAtFrequency_Sampled(double frequency_of_occurance) {
double probabilityUnderFrequency = 0;
for (int y = sampledHistogram_Humidity.length - 1; y >= 0; y--) {
for (int x = sampledHistogram_Heat.length - 1; x >= 0; x--) {
double probability = (sampledHistogram_Heat[x] / dataSampleCount) * (sampledHistogram_Humidity[y] / dataSampleCount);
if (probability <= frequency_of_occurance) {
probabilityUnderFrequency += probability;
}
}
}
return probabilityUnderFrequency * 100;
}
/**
* Returns the percentage of sample locations/bins that occur at or below the given frequency_of_occurance,
* however it uses the processed data, rather than the real samples.
* @see PercentileAtFrequency_Sampled
*/
private double PercentileAtFrequency_Processed(double frequency_of_occurance) {
double probabilityUnderFrequency = 0;
for (int y = processedHistogram_Humidity.length - 1; y >= 0; y--) {
for (int x = processedHistogram_Heat.length - 1; x >= 0; x--) {
double probability = (processedHistogram_Heat[x] / dataProcessedCount) * (processedHistogram_Humidity[y] / dataProcessedCount);
if (probability <= frequency_of_occurance) {
probabilityUnderFrequency += probability;
}
}
}
return probabilityUnderFrequency * 100;
}
/**
* Performs a logrithmic search for a frequency_of_occurance which will split the population of
* samples along the given percentile line.
* It uses the processed data, rather than the real samples.
* It's unlikely to find an exact match - such a value might not exist, but it should get close.
* @param percentile - should be between 0 and 100
* @param upper_freq_bound - note this is an exclusive upper bound, the search alg will never try it, though it should get close enough to not matter.
* @param lower_freq_bound - note this is an exclusive lower bound, the search alg will never try it, though it should get close enough to not matter.
* @param search_depth - recurse depth, and how many calls to FrequencyAtPercentile() will be made.
*/
private double SearchForFrequencyAtPercentile(double percentile, double upper_freq_bound, double lower_freq_bound, int search_depth) {
double midPointFrequency = lower_freq_bound + ((upper_freq_bound - lower_freq_bound) / 2.0d);
double midpointPercentile = PercentileAtFrequency_Processed(midPointFrequency);
if (search_depth == 0) {
AmidstLogger.warn("Could not find exact FrequencyAtPercentile for " + percentile + ", returning " + midPointFrequency);
return midPointFrequency;
}
if (midpointPercentile < percentile) {
return SearchForFrequencyAtPercentile(percentile, upper_freq_bound, midPointFrequency, search_depth - 1);
} else if (midpointPercentile > percentile) {
return SearchForFrequencyAtPercentile(percentile, midPointFrequency, lower_freq_bound, search_depth - 1);
} else {
return midPointFrequency;
}
}
/**
* Processes the sample counts from sampledHistogram_Heat & sampledHistogram_Humidity and
* uses what we know about the climate noise algorithm (the center and symmetry) to create
* data likely to be closer to the true distribution.
*
* This matters if you want quartile lines to look smooth.
*
* The processed data is written to processedHistogram_Heat/processedHistogram_Humidity
*/
private void processSamples() {
int center = Math.round(DEFAULT_OFFSET + offsetAdj);
int distFromCenter = 0;
int maxDistFromCenter = Math.max(center - dataSampleOffset, Math.max(sampledHistogram_Heat.length - center - 1, sampledHistogram_Humidity.length - center - 1));
while (distFromCenter <= maxDistFromCenter) {
int indexLeft = (center + dataSampleOffset) - distFromCenter;
int indexRight = (center + dataSampleOffset) + distFromCenter;
if (indexRight > 0 && indexRight < processedHistogram_Heat.length) {
processedHistogram_Heat[indexRight] = (indexRight < sampledHistogram_Heat.length) ? sampledHistogram_Heat[indexRight] : 0;
if (indexRight < sampledHistogram_Humidity.length) processedHistogram_Heat[indexRight] += sampledHistogram_Humidity[indexRight];
if (indexLeft > 0) {
processedHistogram_Heat[indexRight] += sampledHistogram_Heat[indexLeft];
processedHistogram_Heat[indexRight] += sampledHistogram_Humidity[indexLeft];
// Mirror the processed value to the left side of processedHistogram_Heat
processedHistogram_Heat[indexLeft] = processedHistogram_Heat[indexRight];
}
}
distFromCenter++;
}
// each value in processedHistogram_Heat is now the left+right of both heat+humidy added together
dataProcessedCount = dataSampleCount * 4;
AmidstLogger.info("processedHistogram_Heat: " + Arrays.toString(processedHistogram_Heat));
}
/**
* Caches results from SearchForFrequencyAtPercentile() into frequencyAtPercentileTable and
* frequencyAtPerdimileTable.
* @see SearchForFrequencyAtPercentile
*/
private void calculatePercentileTables(int search_depth) {
LongSummaryStatistics heatStats = Arrays.stream(processedHistogram_Heat).summaryStatistics();
LongSummaryStatistics humidityStats = Arrays.stream(processedHistogram_Humidity).summaryStatistics();
frequencyAtPerdimileTable[0] = (heatStats.getMin() / (double)dataProcessedCount) * (humidityStats.getMin() / (double)dataProcessedCount);
frequencyAtPercentileTable[99] = (heatStats.getMax() / (double)dataProcessedCount) * (humidityStats.getMax() / (double)dataProcessedCount);
double lowerBound_percentile = frequencyAtPerdimileTable[0];
double lowerBound_perdimile = frequencyAtPerdimileTable[0];
for(int i = 1; i < 100; i++) {
frequencyAtPercentileTable[i - 1] = SearchForFrequencyAtPercentile(i, 1.00, lowerBound_percentile, search_depth);
frequencyAtPerdimileTable[i] = SearchForFrequencyAtPercentile(i / 100d, frequencyAtPercentileTable[0], lowerBound_perdimile, search_depth);
lowerBound_percentile = frequencyAtPercentileTable[i];
lowerBound_perdimile = frequencyAtPerdimileTable[i];
}
AmidstLogger.info("frequencyAtPercentileTable: " + Arrays.toString(frequencyAtPercentileTable));
AmidstLogger.info("frequencyAtPerdimileTable: " + Arrays.toString(frequencyAtPerdimileTable));
}
/**
* Constructor for Minetest's default climate
*/
public ClimateHistogram() {
if (dataProcessedCount == 0) {
// the samples are already processed, and the percentile tables already
// calculated, but I leave this code here in case someone wants to update
// sampledHistogram_Heat and sampledHistogram_Humidity with their own sampled
// data and recalculate.
processSamples();
calculatePercentileTables(40);
}
}
/**
* Constructor for climates which have the same frequency distribution as Minetest's default climate,
* but may have been scaled or translated.
*/
public ClimateHistogram(NoiseParams heat, NoiseParams heat_blend, NoiseParams humidity, NoiseParams humidity_blend) {
// Ensure these noise settings are close enough to Minetest's default settings
// that we can use the pre-generated data.
//
// Defaults:
// np_heat = new NoiseParams(50, 50, new Vector3f(1000, 1000, 1000), 5349, (short)3, 0.5f, 2.0f);
// np_humidity = new NoiseParams(50, 50, new Vector3f(1000, 1000, 1000), 842, (short)3, 0.5f, 2.0f);
// np_heat_blend = new NoiseParams( 0, 1.5f, new Vector3f( 8, 8, 8), 13, (short)2, 1.0f, 2.0f);
// np_humidity_blend = new NoiseParams( 0, 1.5f, new Vector3f( 8, 8, 8), 90003, (short)2, 1.0f, 2.0f);
// TODO: Check octaves, persist, and lacunarity are all the same, and that scale and offset
// is the same or can be adjusted for, and that spread is appropriate.
scaleAdj = heat.scale / DEFAULT_SCALE;
offsetAdj = DEFAULT_OFFSET - heat.offset;
float scaleAdj_blend = heat_blend.scale / DEFAULT_BLEND_SCALE;
float offsetAdj_blend = DEFAULT_BLEND_OFFSET - heat_blend.offset;
if (heat.scale != humidity.scale || heat.offset != humidity.offset ||
heat_blend.scale != humidity_blend.scale || heat_blend.offset != humidity_blend.offset ||
scaleAdj != scaleAdj_blend || offsetAdj != offsetAdj_blend ||
heat.octaves != 3 || humidity.octaves != 3 || heat_blend.octaves != 2 || humidity_blend.octaves != 2 ||
heat.persist != 0.5f || humidity.persist != 0.5f || heat_blend.persist != 1.0f || humidity_blend.persist != 1.0f ||
heat.lacunarity != 2.0f || humidity.lacunarity != 2.0f || heat_blend.lacunarity != 2.0f || humidity_blend.lacunarity != 2.0f) {
AmidstLogger.error("Non-standant climate noise in use, current ClimateHistogram instance will give wrong data.");
}
}
}