19using NodataIntType = int64_t;
32 const Location& location)
const noexcept
34 return location.hash();
72 [[nodiscard]]
constexpr MathSize
cellSize() const noexcept
100 [[nodiscard]]
constexpr MathSize
xllcorner() const noexcept
108 [[nodiscard]]
constexpr MathSize
yllcorner() const noexcept
116 [[nodiscard]]
constexpr MathSize
xurcorner() const noexcept
124 [[nodiscard]]
constexpr MathSize
yurcorner() const noexcept
132 [[nodiscard]]
constexpr const string&
proj4() const noexcept
150 string&&
proj4)
noexcept;
160 void createPrj(const
string& dir, const
string& base_name) const;
168 const topo::Point& point,
177 const topo::Point& point,
205void write_ascii_header(ofstream& out,
206 MathSize num_columns,
213[[nodiscard]] R with_tiff(const
string& filename, function<R(TIFF*, GTIF*)> fct)
215 logging::debug(
"Reading file %s", filename.c_str());
217 TIFFSetWarningHandler(
nullptr);
218 auto tif = GeoTiffOpen(filename.c_str(),
"r");
219 logging::check_fatal(!tif,
"Cannot open file %s as a TIF", filename.c_str());
220 auto gtif = GTIFNew(tif);
221 logging::check_fatal(!gtif,
"Cannot open file %s as a GEOTIFF", filename.c_str());
224 R result = fct(tif, gtif);
241GridBase read_header(TIFF* tif, GTIF* gtif);
242GridBase read_header(
const string& filename);
248template <
class T,
class V = T>
257 [[nodiscard]]
constexpr Idx
rows() const noexcept
265 [[nodiscard]]
constexpr Idx
columns() const noexcept
275 return nodata_input_;
283 return nodata_value_;
290 [[nodiscard]]
virtual T
at(
const Location& location)
const = 0;
292 [[nodiscard]] T at(
const Position<P>& position)
const
305 void set(
const Position<P>& position,
const T value)
325 const V nodata_input,
326 const T nodata_value,
327 const MathSize xllcorner,
328 const MathSize yllcorner,
329 const MathSize xurcorner,
330 const MathSize yurcorner,
331 string&& proj4) noexcept
337 std::forward<string>(proj4)),
338 nodata_input_(nodata_input),
339 nodata_value_(nodata_value),
344 logging::check_fatal(rows > MAX_ROWS,
"Too many rows (%d > %d)", rows, MAX_ROWS);
345 logging::check_fatal(columns > MAX_COLUMNS,
"Too many columns (%d > %d)", columns, MAX_COLUMNS);
349 const auto n0 = this->nodata_input_;
350 const auto n1 =
static_cast<NodataIntType
>(n0);
351 const auto n2 =
static_cast<V
>(n1);
352 const auto n3 =
static_cast<NodataIntType
>(n2);
353 logging::check_equal(
356 "nodata_input_ as int");
357 logging::check_equal(
360 "nodata_input_ from int");
369 :
Grid(grid_info.cellSize(),
370 static_cast<Idx
>(grid_info.calculateRows()),
371 static_cast<Idx
>(grid_info.calculateColumns()),
374 grid_info.xllcorner(),
375 grid_info.yllcorner(),
376 grid_info.xurcorner(),
377 grid_info.yurcorner(),
405template <
class T,
class V,
class D>
410 using Grid<T, V>::Grid;
428 const V nodata_input,
429 const T nodata_value,
430 const MathSize xllcorner,
431 const MathSize yllcorner,
432 const MathSize xurcorner,
433 const MathSize yurcorner,
436 :
Grid<T, V>(cell_size,
445 std::forward<string>(proj4)),
446 data(std::forward<D>(data))
455 :
Grid<T, V>(rhs), data(rhs.data)
490 data = std::move(rhs.data);
498 [[nodiscard]]
size_t size()
const
508 virtual tuple<Idx, Idx, Idx, Idx> dataBounds()
const = 0;
519 const string& base_name,
520 std::function<R(T value)> convert,
521 const R no_data)
const
523 tuple<Idx, Idx, Idx, Idx> bounds = dataBounds();
524 auto min_column = std::get<0>(bounds);
525 auto min_row = std::get<1>(bounds);
526 auto max_column = std::get<2>(bounds);
527 auto max_row = std::get<3>(bounds);
530 "Bounds are (%d, %d), (%d, %d)",
536 logging::extensive(
"Lower left corner is (%d, %d)", min_column, min_row);
537 logging::extensive(
"Upper right corner is (%d, %d)", max_column, max_row);
538 const MathSize xll = this->xllcorner() + min_column * this->cellSize();
540 const MathSize yll = this->yllcorner() + (min_row) * this->cellSize();
541 logging::extensive(
"Lower left corner is (%f, %f)", xll, yll);
543 const auto num_rows =
static_cast<MathSize
>(max_row) - min_row + 1;
544 const auto num_columns =
static_cast<MathSize
>(max_column) - min_column + 1;
546 string filename = dir + base_name +
".asc";
547 out.open(filename.c_str());
555 static_cast<MathSize
>(no_data));
556 for (Idx ro = 0; ro < num_rows; ++ro)
560 const Idx r =
static_cast<Idx
>(max_row) - ro;
561 for (Idx co = 0; co < num_columns; ++co)
563 const Location idx(
static_cast<Idx
>(r),
static_cast<Idx
>(min_column + co));
566 out << +(convert(this->at(idx)))
572 this->createPrj(dir, base_name);
584 const string& base_name,
585 std::function<R(T value)> convert,
586 const R no_data)
const
588 uint32_t tileWidth = min((
int)(this->columns()), 256);
589 uint32_t tileHeight = min((
int)(this->rows()), 256);
590 tuple<Idx, Idx, Idx, Idx> bounds = dataBounds();
591 auto min_column = std::get<0>(bounds);
592 auto min_row = std::get<1>(bounds);
593 auto max_column = std::get<2>(bounds);
594 auto max_row = std::get<3>(bounds);
595 logging::check_fatal(
596 min_column > max_column,
597 "Invalid bounds for columns with %d => %d",
600 logging::check_fatal(
602 "Invalid bounds for rows with %d => %d",
607 "Bounds are (%d, %d), (%d, %d) initially",
614 while (c_min +
static_cast<Idx
>(tileWidth) <= min_column)
616 c_min +=
static_cast<Idx
>(tileWidth);
618 Idx c_max = c_min +
static_cast<Idx
>(tileWidth);
619 while (c_max < max_column)
621 c_max +=
static_cast<Idx
>(tileWidth);
626 while (r_min +
static_cast<Idx
>(tileHeight) <= min_row)
628 r_min +=
static_cast<Idx
>(tileHeight);
630 Idx r_max = r_min +
static_cast<Idx
>(tileHeight);
631 while (r_max < max_row)
633 r_max +=
static_cast<Idx
>(tileHeight);
637 logging::check_fatal(
638 min_column >= max_column,
639 "Invalid bounds for columns with %d => %d",
642 logging::check_fatal(
644 "Invalid bounds for rows with %d => %d",
649 "Bounds are (%d, %d), (%d, %d) after correction",
655 logging::extensive(
"(%d, %d) => (%d, %d)", min_column, min_row, max_column, max_row);
656 logging::check_fatal((max_row - min_row) % tileHeight != 0,
"Invalid start and end rows");
657 logging::check_fatal((max_column - min_column) % tileHeight != 0,
"Invalid start and end columns");
658 logging::extensive(
"Lower left corner is (%d, %d)", min_column, min_row);
659 logging::extensive(
"Upper right corner is (%d, %d)", max_column, max_row);
660 const MathSize xll = this->xllcorner() + min_column * this->cellSize();
662 const MathSize yll = this->yllcorner() + (min_row) * this->cellSize();
663 logging::extensive(
"Lower left corner is (%f, %f)", xll, yll);
664 const auto num_rows =
static_cast<size_t>(max_row - min_row);
665 const auto num_columns =
static_cast<size_t>(max_column - min_column);
667 logging::check_fatal(0 != (num_rows % tileWidth),
"%d rows not divisible by tiles", num_rows);
668 logging::check_fatal(0 != (num_columns % tileHeight),
"%d columns not divisible by tiles", num_columns);
669 string filename = dir + base_name +
".tif";
670 TIFF* tif = GeoTiffOpen(filename.c_str(),
"w");
671 auto gtif = GTIFNew(tif);
672 logging::check_fatal(!gtif,
"Cannot open file %s as a GEOTIFF", filename.c_str());
673 const double xul = xll;
674 const double yul = this->yllcorner() + (this->cellSize() * max_row);
675 double tiePoints[6] = {
682 double pixelScale[3] = {
686 uint32_t bps =
sizeof(R) * 8;
688 if (std::is_floating_point<R>::value)
690 logging::extensive(
"Writing %s with float data type for %s",
693 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
697 logging::extensive(
"Writing %s with int data type for %s",
703 constexpr auto n = std::numeric_limits<V>::digits10;
704 static_assert(n > 0);
706 const auto nodata_as_int =
static_cast<int>(this->nodataInput());
707 sxprintf(str,
"%d.000", nodata_as_int);
709 "%s using nodata string '%s' for nodata value of (%d, %f)",
713 static_cast<MathSize
>(no_data));
714 TIFFSetField(tif, TIFFTAG_GDAL_NODATA, str);
715 logging::extensive(
"%s takes %d bits", base_name.c_str(), bps);
716 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, num_columns);
717 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, num_rows);
718 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
719 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
720 TIFFSetField(tif, TIFFTAG_TILEWIDTH, tileWidth);
721 TIFFSetField(tif, TIFFTAG_TILELENGTH, tileHeight);
722 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
723 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
724 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
725 GTIFSetFromProj4(gtif, this->proj4().c_str());
726 TIFFSetField(tif, TIFFTAG_GEOTIEPOINTS, 6, tiePoints);
727 TIFFSetField(tif, TIFFTAG_GEOPIXELSCALE, 3, pixelScale);
728 size_t tileSize = tileWidth * tileHeight;
729 const auto buf_size = tileSize *
sizeof(R);
730 logging::extensive(
"%s has buffer size %d", base_name.c_str(), buf_size);
731 R* buf = (R*)_TIFFmalloc(buf_size);
732 for (
size_t co = 0; co < num_columns; co += tileWidth)
734 for (
size_t ro = 0; ro < num_rows; ro += tileHeight)
738 tileWidth * tileHeight,
742 for (
size_t x = 0; x < tileWidth; ++x)
744 for (
size_t y = 0; y < tileHeight; ++y)
746 const Idx r =
static_cast<Idx
>(max_row) - (ro + y + 1);
747 const Idx c =
static_cast<Idx
>(min_column) + co + x;
750 if (!(this->rows() <= r
752 || this->columns() <= c
756 const R value = convert(this->at(idx));
757 buf[x + y * tileWidth] = value;
761 logging::check_fatal(TIFFWriteTile(tif, buf, co, ro, 0, 0) < 0,
"Cannot write tile to %s", filename.c_str());
784 const string& base_name,
785 std::function<R(T value)> convert,
786 const R no_data)
const
791 return this->
template saveToAsciiFile<R>(
799 return this->
template saveToTiffFile<R>(
816 const string& base_name,
817 std::function<R(T value)> convert,
818 const R no_data)
const
824 return this->
template saveToFileWithoutRetry<R>(dir, base_name, convert, no_data);
826 catch (
const std::exception& err)
828 logging::error(
"Error trying to write %s to %s so retrying\n%s",
834 return this->
template saveToFileWithoutRetry<R>(dir, base_name, convert, no_data);
836 catch (
const std::exception& err_fatal)
839 return logging::fatal<string>(
840 "Error trying to write %s to %s\n%s",
857 const string& base_name,
858 std::function<R(T value)> convert,
859 const R no_data)
const
861 return this->
template saveToFileWithRetry<R>(dir, base_name, convert, no_data);
872 const string& base_name,
873 std::function<R(T value)> convert)
const
875 return this->
template saveToFile<R>(dir, base_name, convert,
static_cast<R
>(this->nodataInput()));
882 template <
class R = V>
883 string saveToFile(
const string& dir,
const string& base_name)
const
885 return this->
template saveToFile<R>(
889 return static_cast<R
>(value);
The base class with information for a grid of data with geographic coordinates.
Definition Grid.h:43
constexpr MathSize xurcorner() const noexcept
Upper right corner X coordinate in meters.
Definition Grid.h:116
unique_ptr< FullCoordinates > findFullCoordinates(const topo::Point &point, bool flipped) const
Find FullCoordinates for Point.
Definition Grid.cpp:127
MathSize cell_size_
Cell height and width in meters.
Definition Grid.h:187
GridBase & operator=(const GridBase &rhs)=default
Copy assignment.
constexpr const string & proj4() const noexcept
Proj4 string defining coordinate system for this grid. Must be a UTM projection.
Definition Grid.h:132
constexpr FullIdx calculateRows() const noexcept
Number of rows in the GridBase.
Definition Grid.h:80
void createPrj(const string &dir, const string &base_name) const
Create .prj file in directory with base name for file.
Definition Grid.cpp:72
constexpr MathSize cellSize() const noexcept
Cell size used for GridBase.
Definition Grid.h:72
constexpr MathSize yllcorner() const noexcept
Lower left corner Y coordinate in meters.
Definition Grid.h:108
GridBase(const GridBase &rhs)=default
Copy constructor.
MathSize xllcorner_
Lower left corner X coordinate in meters.
Definition Grid.h:191
MathSize yurcorner_
Upper right corner Y coordinate in meters.
Definition Grid.h:203
GridBase() noexcept
Default constructor.
Definition Grid.cpp:64
GridBase(GridBase &&rhs) noexcept=default
Move constructor.
constexpr MathSize xllcorner() const noexcept
Lower left corner X coordinate in meters.
Definition Grid.h:100
MathSize xurcorner_
Upper right corner X coordinate in meters.
Definition Grid.h:199
MathSize yllcorner_
Lower left corner Y coordinate in meters.
Definition Grid.h:195
constexpr MathSize yurcorner() const noexcept
Upper right corner Y coordinate in meters.
Definition Grid.h:124
constexpr FullIdx calculateColumns() const noexcept
Number of columns in the GridBase.
Definition Grid.h:90
string proj4_
Proj4 string defining projection.
Definition Grid.h:183
unique_ptr< Coordinates > findCoordinates(const topo::Point &point, bool flipped) const
Find Coordinates for Point.
Definition Grid.cpp:116
GridBase & operator=(GridBase &&rhs) noexcept=default
Move assignment.
A Grid that defines the data structure used for storing values.
Definition Grid.h:408
string saveToFileWithRetry(const string &dir, const string &base_name, std::function< R(T value)> convert, const R no_data) const
Save GridMap contents to file based on settings.
Definition Grid.h:815
string saveToFileWithoutRetry(const string &dir, const string &base_name, std::function< R(T value)> convert, const R no_data) const
Save GridMap contents to file based on settings.
Definition Grid.h:783
GridData(const MathSize cell_size, const Idx rows, const Idx columns, const V nodata_input, const T nodata_value, const MathSize xllcorner, const MathSize yllcorner, const MathSize xurcorner, const MathSize yurcorner, string &&proj4, D &&data)
Constructor.
Definition Grid.h:425
string saveToFile(const string &dir, const string &base_name, std::function< R(T value)> convert, const R no_data) const
Save GridMap contents to file based on settings.
Definition Grid.h:856
size_t size() const
Size of data structure storing values.
Definition Grid.h:498
D data
Structure that holds data represented by this GridData.
Definition Grid.h:506
GridData(GridData &&rhs) noexcept
Move constructor.
Definition Grid.h:462
GridData & operator=(GridData &&rhs) noexcept
Move assignment.
Definition Grid.h:485
string saveToFile(const string &dir, const string &base_name, std::function< R(T value)> convert) const
Save GridMap contents to file based on settings.
Definition Grid.h:871
string saveToAsciiFile(const string &dir, const string &base_name, std::function< R(T value)> convert, const R no_data) const
Save GridMap contents to .asc file.
Definition Grid.h:518
string saveToFile(const string &dir, const string &base_name) const
Save GridMap contents to file based on settings.
Definition Grid.h:883
GridData(const GridData &rhs)
Copy constructor.
Definition Grid.h:454
GridData & operator=(const GridData &rhs) noexcept
Copy assignment.
Definition Grid.h:471
string saveToTiffFile(const string &dir, const string &base_name, std::function< R(T value)> convert, const R no_data) const
Save GridMap contents to .tif file.
Definition Grid.h:583
A GridBase with an associated type of data.
Definition Grid.h:251
constexpr V nodataInput() const noexcept
Value used for grid locations that have no data.
Definition Grid.h:273
constexpr Idx rows() const noexcept
Number of rows in the GridBase.
Definition Grid.h:257
Grid(const MathSize cell_size, const Idx rows, const Idx columns, const V nodata_input, const T nodata_value, const MathSize xllcorner, const MathSize yllcorner, const MathSize xurcorner, const MathSize yurcorner, string &&proj4) noexcept
Constructor.
Definition Grid.h:322
constexpr Idx columns() const noexcept
Number of columns in the GridBase.
Definition Grid.h:265
virtual T at(const Location &location) const =0
Value for grid at given Location.
Grid(const GridBase &grid_info, V no_data) noexcept
Construct based on GridBase and no data value.
Definition Grid.h:368
T nodata_value_
Value to use for representing no data at a Location.
Definition Grid.h:389
virtual void set(const Location &location, T value)=0
Set value for grid at given Location.
constexpr T nodataValue() const noexcept
Value representing no data.
Definition Grid.h:281
V nodata_input_
Value used to represent no data at a Location.
Definition Grid.h:385
static bool saveAsAscii() noexcept
Whether or not to save grids as .asc.
Definition Settings.cpp:632
Definition Location.h:229
A Position with a row and column.
Definition Location.h:57
constexpr HashSize hash() const noexcept
Hash derived from row and column.
Definition Location.h:80
constexpr fs::HashSize operator()(const Location &location) const noexcept
Get hash value for a Location.
Definition Grid.h:31