FireSTARR
Loading...
Searching...
No Matches
Grid.h
1/* Copyright (c) Queen's Printer for Ontario, 2020. */
2/* Copyright (c) His Majesty the King in Right of Canada as represented by the Minister of Natural Resources, 2021-2025. */
3
4/* SPDX-License-Identifier: AGPL-3.0-or-later */
5
6#pragma once
7#include <limits>
8#include <memory>
9#include <string>
10#include <utility>
11#include "Location.h"
12#include "Cell.h"
13#include "Log.h"
14#include "Point.h"
15#include "Settings.h"
16
19using NodataIntType = int64_t;
23template <>
24struct std::hash<Location>
25{
31 [[nodiscard]] constexpr fs::HashSize operator()(
32 const Location& location) const noexcept
33 {
34 return location.hash();
35 }
36};
37namespace fs::data
38{
43{
44public:
45 virtual ~GridBase() = default;
50 GridBase(GridBase&& rhs) noexcept = default;
55 GridBase(const GridBase& rhs) = default;
61 GridBase& operator=(const GridBase& rhs) = default;
67 GridBase& operator=(GridBase&& rhs) noexcept = default;
72 [[nodiscard]] constexpr MathSize cellSize() const noexcept
73 {
74 return cell_size_;
75 }
80 [[nodiscard]] constexpr FullIdx calculateRows() const noexcept
81 {
82 return static_cast<FullIdx>((yurcorner() - yllcorner()) / cellSize()) - 1;
83 // // HACK: just get rid of -1 for now because it seems weird
84 // return static_cast<FullIdx>((yurcorner() - yllcorner()) / cellSize());
85 }
90 [[nodiscard]] constexpr FullIdx calculateColumns() const noexcept
91 {
92 return static_cast<FullIdx>((xurcorner() - xllcorner()) / cellSize()) - 1;
93 // // HACK: just get rid of -1 for now because it seems weird
94 // return static_cast<FullIdx>((xurcorner() - xllcorner()) / cellSize());
95 }
100 [[nodiscard]] constexpr MathSize xllcorner() const noexcept
101 {
102 return xllcorner_;
103 }
108 [[nodiscard]] constexpr MathSize yllcorner() const noexcept
109 {
110 return yllcorner_;
111 }
116 [[nodiscard]] constexpr MathSize xurcorner() const noexcept
117 {
118 return xurcorner_;
119 }
124 [[nodiscard]] constexpr MathSize yurcorner() const noexcept
125 {
126 return yurcorner_;
127 }
132 [[nodiscard]] constexpr const string& proj4() const noexcept
133 {
134 return proj4_;
135 }
145 GridBase(MathSize cell_size,
146 MathSize xllcorner,
147 MathSize yllcorner,
148 MathSize xurcorner,
149 MathSize yurcorner,
150 string&& proj4) noexcept;
154 GridBase() noexcept;
160 void createPrj(const string& dir, const string& base_name) const;
167 [[nodiscard]] unique_ptr<Coordinates> findCoordinates(
168 const topo::Point& point,
169 bool flipped) const;
176 [[nodiscard]] unique_ptr<FullCoordinates> findFullCoordinates(
177 const topo::Point& point,
178 bool flipped) const;
179private:
183 string proj4_;
187 MathSize cell_size_;
191 MathSize xllcorner_;
195 MathSize yllcorner_;
199 MathSize xurcorner_;
203 MathSize yurcorner_;
204};
205void write_ascii_header(ofstream& out,
206 MathSize num_columns,
207 MathSize num_rows,
208 MathSize xll,
209 MathSize yll,
210 MathSize cell_size,
211 MathSize no_data);
212template <class R>
213[[nodiscard]] R with_tiff(const string& filename, function<R(TIFF*, GTIF*)> fct)
214{
215 logging::debug("Reading file %s", filename.c_str());
216 // suppress warnings about geotiff tags that aren't found
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());
222 // try
223 // {
224 R result = fct(tif, gtif);
225 if (tif)
226 {
227 XTIFFClose(tif);
228 }
229 if (gtif)
230 {
231 GTIFFree(gtif);
232 }
233 GTIFDeaccessCSV();
234 return result;
235 // }
236 // catch (std::exception&)
237 // {
238 // return logging::fatal<R>("Unable to process file %s", filename.c_str());
239 // }
240}
241GridBase read_header(TIFF* tif, GTIF* gtif);
242GridBase read_header(const string& filename);
248template <class T, class V = T>
249class Grid
250 : public GridBase
251{
252public:
257 [[nodiscard]] constexpr Idx rows() const noexcept
258 {
259 return rows_;
260 }
265 [[nodiscard]] constexpr Idx columns() const noexcept
266 {
267 return columns_;
268 }
273 [[nodiscard]] constexpr V nodataInput() const noexcept
274 {
275 return nodata_input_;
276 }
281 constexpr T nodataValue() const noexcept
282 {
283 return nodata_value_;
284 } // NOTE: only use this for simple types because it's returning by value
290 [[nodiscard]] virtual T at(const Location& location) const = 0;
291 template <class P>
292 [[nodiscard]] T at(const Position<P>& position) const
293 {
294 return at(Location{position.hash()});
295 }
296 // NOTE: use set instead of at to avoid issues with bool
303 virtual void set(const Location& location, T value) = 0;
304 template <class P>
305 void set(const Position<P>& position, const T value)
306 {
307 set(Location{position.hash()});
308 }
309protected:
322 Grid(const MathSize cell_size,
323 const Idx rows,
324 const Idx columns,
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
332 : GridBase(cell_size,
333 xllcorner,
334 yllcorner,
335 xurcorner,
336 yurcorner,
337 std::forward<string>(proj4)),
338 nodata_input_(nodata_input),
339 nodata_value_(nodata_value),
340 rows_(rows),
341 columns_(columns)
342 {
343#ifdef DEBUG_GRIDS
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);
346#endif
347#ifdef DEBUG_GRIDS
348 // enforce converting to an int and back produces same V
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(
354 n1,
355 n3,
356 "nodata_input_ as int");
357 logging::check_equal(
358 n0,
359 n2,
360 "nodata_input_ from int");
361#endif
362 }
368 Grid(const GridBase& grid_info, V no_data) noexcept
369 : Grid(grid_info.cellSize(),
370 static_cast<Idx>(grid_info.calculateRows()),
371 static_cast<Idx>(grid_info.calculateColumns()),
372 no_data,
373 to_string(no_data),
374 grid_info.xllcorner(),
375 grid_info.yllcorner(),
376 grid_info.xurcorner(),
377 grid_info.yurcorner(),
378 grid_info.proj4())
379 {
380 }
381private:
393 Idx rows_{};
397 Idx columns_{};
398};
405template <class T, class V, class D>
407 : public Grid<T, V>
408{
409public:
410 using Grid<T, V>::Grid;
425 GridData(const MathSize cell_size,
426 const Idx rows,
427 const Idx columns,
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,
434 string&& proj4,
435 D&& data)
436 : Grid<T, V>(cell_size,
437 rows,
438 columns,
439 nodata_input,
440 nodata_value,
441 xllcorner,
442 yllcorner,
443 xurcorner,
444 yurcorner,
445 std::forward<string>(proj4)),
446 data(std::forward<D>(data))
447 {
448 }
449 ~GridData() = default;
454 GridData(const GridData& rhs)
455 : Grid<T, V>(rhs), data(rhs.data)
456 {
457 }
462 GridData(GridData&& rhs) noexcept
463 : Grid<T, V>(rhs), data(std::move(rhs.data))
464 {
465 }
471 GridData& operator=(const GridData& rhs) noexcept
472 {
473 if (this != &rhs)
474 {
476 data = rhs.data;
477 }
478 return *this;
479 }
485 GridData& operator=(GridData&& rhs) noexcept
486 {
487 if (this != &rhs)
488 {
490 data = std::move(rhs.data);
491 }
492 return *this;
493 }
498 [[nodiscard]] size_t size() const
499 {
500 return data.size();
501 }
502 // HACK: use public access so that we can get to the keys
507protected:
508 virtual tuple<Idx, Idx, Idx, Idx> dataBounds() const = 0;
517 template <class R>
518 string saveToAsciiFile(const string& dir,
519 const string& base_name,
520 std::function<R(T value)> convert,
521 const R no_data) const
522 {
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);
528#ifdef DEBUG_GRIDS
529 logging::debug(
530 "Bounds are (%d, %d), (%d, %d)",
531 min_column,
532 min_row,
533 max_column,
534 max_row);
535#endif
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();
539 // offset is different for y since it's flipped
540 const MathSize yll = this->yllcorner() + (min_row) * this->cellSize();
541 logging::extensive("Lower left corner is (%f, %f)", xll, yll);
542 // HACK: make sure it's always at least 1
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;
545 ofstream out;
546 string filename = dir + base_name + ".asc";
547 out.open(filename.c_str());
548 write_ascii_header(
549 out,
550 num_columns,
551 num_rows,
552 xll,
553 yll,
554 this->cellSize(),
555 static_cast<MathSize>(no_data));
556 for (Idx ro = 0; ro < num_rows; ++ro)
557 {
558 // HACK: do this so that we always get at least one pixel in output
559 // need to output in reverse order since (0,0) is bottom left
560 const Idx r = static_cast<Idx>(max_row) - ro;
561 for (Idx co = 0; co < num_columns; ++co)
562 {
563 const Location idx(static_cast<Idx>(r), static_cast<Idx>(min_column + co));
564 // HACK: use + here so that it gets promoted to a printable number
565 // prevents char type being output as characters
566 out << +(convert(this->at(idx)))
567 << " ";
568 }
569 out << "\n";
570 }
571 out.close();
572 this->createPrj(dir, base_name);
573 return filename;
574 }
582 template <class R>
583 string saveToTiffFile(const string& dir,
584 const string& base_name,
585 std::function<R(T value)> convert,
586 const R no_data) const
587 {
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",
598 min_column,
599 max_column);
600 logging::check_fatal(
601 min_row > max_row,
602 "Invalid bounds for rows with %d => %d",
603 min_row,
604 max_row);
605#ifdef DEBUG_GRIDS
606 logging::debug(
607 "Bounds are (%d, %d), (%d, %d) initially",
608 min_column,
609 min_row,
610 max_column,
611 max_row);
612#endif
613 Idx c_min = 0;
614 while (c_min + static_cast<Idx>(tileWidth) <= min_column)
615 {
616 c_min += static_cast<Idx>(tileWidth);
617 }
618 Idx c_max = c_min + static_cast<Idx>(tileWidth);
619 while (c_max < max_column)
620 {
621 c_max += static_cast<Idx>(tileWidth);
622 }
623 min_column = c_min;
624 max_column = c_max;
625 Idx r_min = 0;
626 while (r_min + static_cast<Idx>(tileHeight) <= min_row)
627 {
628 r_min += static_cast<Idx>(tileHeight);
629 }
630 Idx r_max = r_min + static_cast<Idx>(tileHeight);
631 while (r_max < max_row)
632 {
633 r_max += static_cast<Idx>(tileHeight);
634 }
635 min_row = r_min;
636 max_row = r_max;
637 logging::check_fatal(
638 min_column >= max_column,
639 "Invalid bounds for columns with %d => %d",
640 min_column,
641 max_column);
642 logging::check_fatal(
643 min_row >= max_row,
644 "Invalid bounds for rows with %d => %d",
645 min_row,
646 max_row);
647#ifdef DEBUG_GRIDS
648 logging::debug(
649 "Bounds are (%d, %d), (%d, %d) after correction",
650 min_column,
651 min_row,
652 max_column,
653 max_row);
654#endif
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();
661 // offset is different for y since it's flipped
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);
666 // ensure this is always divisible by tile size
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] = {
676 0.0,
677 0.0,
678 0.0,
679 xul,
680 yul,
681 0.0};
682 double pixelScale[3] = {
683 this->cellSize(),
684 this->cellSize(),
685 0.0};
686 uint32_t bps = sizeof(R) * 8;
687 // make sure to use floating point if values are
688 if (std::is_floating_point<R>::value)
689 {
690 logging::extensive("Writing %s with float data type for %s",
691 filename.c_str(),
692 typeid(R).name());
693 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
694 }
695 else
696 {
697 logging::extensive("Writing %s with int data type for %s",
698 filename.c_str(),
699 typeid(R).name());
700 }
701 // FIX: was using double, and that usually doesn't make sense, but sometime it might?
702 // use buffer big enought to fit any (V + '.000\0') + 1
703 constexpr auto n = std::numeric_limits<V>::digits10;
704 static_assert(n > 0);
705 char str[n + 6]{0};
706 const auto nodata_as_int = static_cast<int>(this->nodataInput());
707 sxprintf(str, "%d.000", nodata_as_int);
708 logging::extensive(
709 "%s using nodata string '%s' for nodata value of (%d, %f)",
710 typeid(this).name(),
711 str,
712 nodata_as_int,
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)
733 {
734 for (size_t ro = 0; ro < num_rows; ro += tileHeight)
735 {
736 std::fill_n(
737 &buf[0],
738 tileWidth * tileHeight,
739 no_data);
740 // NOTE: shouldn't need to check if writing outside of tile because we made bounds on tile edges above
741 // need to put data from grid into buffer, but flipped vertically
742 for (size_t x = 0; x < tileWidth; ++x)
743 {
744 for (size_t y = 0; y < tileHeight; ++y)
745 {
746 const Idx r = static_cast<Idx>(max_row) - (ro + y + 1);
747 const Idx c = static_cast<Idx>(min_column) + co + x;
748 const Location idx(r, c);
749 // might be out of bounds if not divisible by number of tiles
750 if (!(this->rows() <= r
751 || 0 > r
752 || this->columns() <= c
753 || 0 > c))
754 {
755 // HACK: was getting invalid rasters if assigning directly into buf
756 const R value = convert(this->at(idx));
757 buf[x + y * tileWidth] = value;
758 }
759 }
760 }
761 logging::check_fatal(TIFFWriteTile(tif, buf, co, ro, 0, 0) < 0, "Cannot write tile to %s", filename.c_str());
762 }
763 }
764 GTIFWriteKeys(gtif);
765 if (gtif)
766 {
767 GTIFFree(gtif);
768 }
769 _TIFFfree(buf);
770 TIFFClose(tif);
771 return filename;
772 }
773public:
782 template <class R>
783 string saveToFileWithoutRetry(const string& dir,
784 const string& base_name,
785 std::function<R(T value)> convert,
786 const R no_data) const
787 {
788 // NOTE: do this instead of function pointer because it's using templates
790 {
791 return this->template saveToAsciiFile<R>(
792 dir,
793 base_name,
794 convert,
795 no_data);
796 }
797 else
798 {
799 return this->template saveToTiffFile<R>(
800 dir,
801 base_name,
802 convert,
803 no_data);
804 }
805 }
814 template <class R>
815 string saveToFileWithRetry(const string& dir,
816 const string& base_name,
817 std::function<R(T value)> convert,
818 const R no_data) const
819 {
820 // HACK: (hopefully) ensure that write works
821 try
822 {
823 // HACK: use different function name to prevent infinite recursion warning
824 return this->template saveToFileWithoutRetry<R>(dir, base_name, convert, no_data);
825 }
826 catch (const std::exception& err)
827 {
828 logging::error("Error trying to write %s to %s so retrying\n%s",
829 base_name.c_str(),
830 dir.c_str(),
831 err.what());
832 try
833 {
834 return this->template saveToFileWithoutRetry<R>(dir, base_name, convert, no_data);
835 }
836 catch (const std::exception& err_fatal)
837 {
838 // will exit if not supposed to retry
839 return logging::fatal<string>(
840 "Error trying to write %s to %s\n%s",
841 base_name.c_str(),
842 dir.c_str(),
843 err_fatal.what());
844 }
845 }
846 }
855 template <class R>
856 string saveToFile(const string& dir,
857 const string& base_name,
858 std::function<R(T value)> convert,
859 const R no_data) const
860 {
861 return this->template saveToFileWithRetry<R>(dir, base_name, convert, no_data);
862 }
870 template <class R>
871 string saveToFile(const string& dir,
872 const string& base_name,
873 std::function<R(T value)> convert) const
874 {
875 return this->template saveToFile<R>(dir, base_name, convert, static_cast<R>(this->nodataInput()));
876 }
882 template <class R = V>
883 string saveToFile(const string& dir, const string& base_name) const
884 {
885 return this->template saveToFile<R>(
886 dir,
887 base_name,
888 [](T value) -> R {
889 return static_cast<R>(value);
890 });
891 }
892};
893}
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