49 OGRMultiPolygon *buffInnerPolygons =
new OGRMultiPolygon;
50 OGRMultiPolygon *buffOuterPolygons =
new OGRMultiPolygon;
51 OGRGeometry *p_polygonMask;
54 for (
const auto& p_feature : *p_access->
getLayer(layerName.c_str())) {
55 OGRGeometry *p_geometry = p_feature->GetGeometryRef();
57 throw std::runtime_error(std::format(
"An invalid geometry was encountered in the {} layer.", layerName));
60 OGRwkbGeometryType type = wkbFlatten(p_geometry->getGeometryType());
63 case OGRwkbGeometryType::wkbLineString: {
64 OGRGeometry *p_outer = p_geometry->Buffer(buffOuter);
65 buffOuterPolygons->addGeometry(p_outer);
66 OGRGeometryFactory::destroyGeometry(p_outer);
69 OGRGeometry *p_inner = p_geometry->Buffer(buffInner);
70 buffInnerPolygons->addGeometry(p_inner);
71 OGRGeometryFactory::destroyGeometry(p_inner);
75 case OGRwkbGeometryType::wkbMultiLineString: {
76 for (
const auto& p_lineString : *p_geometry->toMultiLineString()) {
77 OGRGeometry *p_outer = p_geometry->Buffer(buffOuter);
78 buffOuterPolygons->addGeometry(p_outer);
79 OGRGeometryFactory::destroyGeometry(p_outer);
81 OGRGeometry *p_inner = p_geometry->Buffer(buffInner);
82 buffInnerPolygons->addGeometry(p_inner);
83 OGRGeometryFactory::destroyGeometry(p_inner);
89 throw std::runtime_error(
"access polygon geometry type must be LineString or MultiLineString");
96 p_polygonMask = buffOuterPolygons->UnionCascaded();
99 OGRGeometry *buffOuterUnion = buffOuterPolygons->UnionCascaded();
100 OGRGeometry *buffInnerUnion = buffInnerPolygons->UnionCascaded();
101 p_polygonMask = buffOuterUnion->Difference(buffInnerUnion);
102 OGRGeometryFactory::destroyGeometry(buffOuterUnion);
103 OGRGeometryFactory::destroyGeometry(buffInnerUnion);
105 delete buffOuterPolygons;
106 delete buffInnerPolygons;
108 return p_polygonMask;
256 std::string location,
259 std::string layerName,
264 std::optional<uint64_t> random_state,
265 std::string filename)
272 GDALInvGeoTransform(GT, IGT);
275 double xMin, xMax, yMin, yMax;
282 double xDiff = xMax - xMin;
283 double yDiff = yMax - yMin;
284 double rngMax = yDiff * xDiff;
285 std::mt19937 engine(random_state.value_or(std::random_device{}()));
286 std::uniform_real_distribution<double>
dist(0.0, rngMax);
287 auto rng = [&] {
return dist(engine); };
290 double rotation = rng() / (rngMax / 180);
293 std::string gridFunction;
294 if (shape ==
"square") {
295 gridFunction =
"ST_SquareGrid";
298 gridFunction =
"ST_HexagonalGrid";
302 std::string extentPolygon =
"'POLYGON (( "
303 + std::to_string(xMin) +
" " + std::to_string(yMin) +
", "
304 + std::to_string(xMin) +
" " + std::to_string(yMax) +
", "
305 + std::to_string(xMax) +
" " + std::to_string(yMax) +
", "
306 + std::to_string(xMax) +
" " + std::to_string(yMin) +
", "
307 + std::to_string(xMin) +
" " + std::to_string(yMin) +
" ))'";
309 std::string queryString =
"SELECT RotateCoords("
314 +
"), " + std::to_string(-rotation) +
"), "
315 + std::to_string(cellSize) +
"), "
316 + std::to_string(rotation) +
")";
319 OGRLayer *p_grid = p_raster->
getDataset()->ExecuteSQL(queryString.c_str(),
nullptr,
"SQLITE");
322 GDALDriver *p_driver = GetGDALDriverManager()->GetDriverByName(
"MEM");
324 throw std::runtime_error(
"unable to create output sample dataset driver.");
326 GDALDataset *p_sampleDataset = p_driver->Create(
"", 0, 0, 0, GDT_Unknown,
nullptr);
327 if (!p_sampleDataset) {
328 throw std::runtime_error(
"unable to create output dataset with driver.");
332 OGRLayer *p_sampleLayer = p_sampleDataset->CreateLayer(
"samples", p_wrapper->
getSRS(), wkbPoint,
nullptr);
333 if (!p_sampleLayer) {
334 throw std::runtime_error(
"unable to create output dataset layer.");
338 OGRGeometry *
access =
nullptr;
345 buffOuter = buffOuter - pixelSize / 50;
346 buffInner = buffInner == 0 ? 0 : buffInner + pixelSize / 50;
352 std::vector<double> xCoords, yCoords;
359 std::vector<std::vector<std::vector<double>>> grid;
362 for (
const auto& p_feature : *p_grid) {
363 OGRGeometry *p_geometry = p_feature->GetGeometryRef();
365 throw std::runtime_error(
"An invalid geometry was encountered in the grid. This is a bug and should be reported to the sgspy github page.");
367 for (
const auto& p_polygon : *p_geometry->toMultiPolygon()) {
370 OGRPoint secondPoint;
371 if (location ==
"centers") {
372 p_polygon->Centroid(&point);
374 double x = point.getX();
375 double y = point.getY();
386 xCoords.push_back(x);
387 yCoords.push_back(y);
391 else if (location ==
"corners") {
392 (*p_polygon->begin())->getPoint(0, &point);
393 (*p_polygon->begin())->getPoint(1, &secondPoint);
395 double x = point.getX();
396 double y = point.getY();
407 xCoords.push_back(x);
408 yCoords.push_back(y);
412 x = secondPoint.getX();
413 y = secondPoint.getY();
424 xCoords.push_back(x);
425 yCoords.push_back(y);
431 OGREnvelope envelope;
432 p_polygon->getEnvelope(&envelope);
433 double xMinEnv = envelope.MinX;
434 double xMaxEnv = envelope.MaxX;
435 double xDiffEnv = xMaxEnv - xMinEnv;
436 double yMinEnv = envelope.MinY;
437 double yMaxEnv = envelope.MaxY;
438 double yDiffEnv = yMaxEnv - yMinEnv;
443 while (tries < 10 && !found) {
444 point.setX(xMinEnv + rng() / (rngMax / xDiffEnv));
445 point.setY(yMinEnv + rng() / (rngMax / yDiffEnv));
446 while (!p_polygon->Contains(&point)) {
447 point.setX(xMinEnv + rng() / (rngMax / xDiffEnv));
448 point.setY(yMinEnv + rng() / (rngMax / yDiffEnv));
451 double x = point.getX();
452 double y = point.getY();
464 xCoords.push_back(x);
465 yCoords.push_back(y);
476 grid.back().push_back({});
477 grid.back().push_back({});
478 for (
const auto& p_linearRing : *p_polygon) {
479 for (
const auto& p_point : *p_linearRing) {
480 grid.back()[0].push_back(p_point.getX());
481 grid.back()[1].push_back(p_point.getY());
488 if (filename !=
"") {
490 p_wrapper->
write(filename);
492 catch (
const std::exception& e) {
493 std::cout <<
"Exception thrown trying to write file: " << e.what() << std::endl;
498 p_raster->
getDataset()->ReleaseResultSet(p_grid);
500 OGRGeometryFactory::destroyGeometry(
access);
503 return {p_wrapper, {xCoords, yCoords}, grid};