60 std::vector<helper::Index>& indices,
61 xso::xoshiro_4x64_plus rng)
63 T nan =
static_cast<T
>(band.
nan);
65 uint64_t width64 =
static_cast<int64_t
>(width);
66 uint64_t height64 =
static_cast<int64_t
>(height);
69 uint64_t maxIndex = width64 * height64 - 1;
70 uint64_t mask = maxIndex;
79 int maxIterations = numSamples * 11;
80 boost::unordered::unordered_flat_set<uint64_t> indexSet;
81 while (iterations < maxIterations && indices.size() <
static_cast<size_t>(numSamples)) {
85 uint64_t index = (rng() >> 11) & mask;
86 while (index > maxIndex) {
87 index = (rng() >> 11) & mask;
89 int x =
static_cast<int>(index % width64);
90 int y =
static_cast<int>(index / width64);
94 CPLErr err = band.
p_band->RasterIO(GF_Read, x, y, 1, 1, &val, 1, 1, band.
type, 0, 0);
96 throw std::runtime_error(
"error reading pixel from raster band using GDALRasterBand::RasterIO().");
100 bool isNan = std::isnan(val) || val == nan;
107 bool accessible = !
access.used;
110 CPLErr err =
access.band.p_band->RasterIO(GF_Read, x, y, 1, 1, &accessVal, 1, 1,
access.band.type, 0, 0);
112 throw std::runtime_error(
"error reading pixel from access raster band using GDALRasterBand::RasterIO().");
114 accessible = accessVal != 1;
123 alreadySampled |= indexSet.find(index) != indexSet.end();
124 if (alreadySampled) {
130 indexSet.insert(index);
135 return indices.size() ==
static_cast<size_t>(numSamples);
290 std::string layerName,
294 std::string tempFolder,
295 std::string filename)
302 bool useMindist = mindist != 0;
305 std::vector<double> xCoords, yCoords;
306 std::vector<size_t> indexes;
313 band.
nan = band.
p_band->GetNoDataValue();
319 GDALDriver *p_driver = GetGDALDriverManager()->GetDriverByName(
"MEM");
321 throw std::runtime_error(
"unable to create output sample dataset driver.");
323 GDALDataset *p_samples = p_driver->Create(
"", 0, 0, 0, GDT_Unknown,
nullptr);
325 throw std::runtime_error(
"unable to create output dataset with driver.");
329 OGRLayer *p_layer = p_samples->CreateLayer(
"samples", p_wrapper->
getSRS(), wkbPoint,
nullptr);
331 throw std::runtime_error(
"unable to create output dataset layer.");
365 std::vector<helper::Index> indices;
372 xso::xoshiro_4x64_plus rng;
401 size_t numBlocks =
static_cast<size_t>(xBlocks) *
static_cast<size_t>(yBlocks);
404 size_t desiredSamples =
static_cast<size_t>(useMindist ? numSamples * 3 : numSamples);
407 size_t allPixels =
static_cast<size_t>(width) *
static_cast<size_t>(height);
410 double totalArea =
static_cast<double>(p_raster->
getPixelHeight()) *
412 static_cast<double>(allPixels);
415 double accessiblePixels = allPixels * (
access.used ? (
access.area / totalArea) : 1.0);
418 size_t validPixels =
static_cast<size_t>(accessiblePixels / 2.0) - (
existing.used ?
existing.samples.size() : 0);
420 size_t randomAccessBlocksRequired = 0;
422 while (desiredSamples > 0 && randomAccessBlocksRequired < numBlocks) {
432 randomAccessBlocksRequired += (allPixels / validPixels);
438 size_t maxRandomAccessBlocks = randomAccessBlocksRequired + randomAccessBlocksRequired / 4;
444 bool haveEnoughSamples =
false;
445 if (maxRandomAccessBlocks < numBlocks) {
446 desiredSamples =
static_cast<size_t>(useMindist ? numSamples * 3 : numSamples);
471 throw std::runtime_error(
"raster pixel data type not supported.");
475 if (!haveEnoughSamples) {
499 for (
int yBlock = 0; yBlock < yBlocks; yBlock++) {
500 for (
int xBlock = 0; xBlock < xBlocks; xBlock++) {
504 band.
p_band->GetActualBlockSize(xBlock, yBlock, &xValid, &yValid);
539 throw std::runtime_error(
"raster pixel data type is not supported.");
545 std::shuffle(indices.begin(), indices.end(), rng);
550 double mindist_sq = mindist * mindist;
553 while (samplesAdded < numSamples && i < indices.size()) {
563 OGRPoint point = OGRPoint(x, y);
572 xCoords.push_back(x);
573 yCoords.push_back(y);
580 if (filename !=
"") {
582 p_wrapper->
write(filename);
584 catch (
const std::exception& e) {
585 std::cout <<
"Exception thrown trying to write file: " << e.what() << std::endl;
592 VSIFree(
access.band.p_buffer);
595 return {{xCoords, yCoords}, p_wrapper, samplesAdded};