1 // Copyright (c) 2018-2020  Robert J. Hijmans
2 //
3 // This file is part of the "spat" library.
4 //
5 // spat is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // spat is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with spat. If not, see <http://www.gnu.org/licenses/>.
17 
18 #include "spatRaster.h"
19 
20 
21 // A collection of (perhaps non matching) SpatRasters
22 class SpatRasterCollection {
23 	public:
24 		SpatMessages msg;
setError(std::string s)25 		void setError(std::string s) { msg.setError(s); }
addWarning(std::string s)26 		void addWarning(std::string s) { msg.addWarning(s); }
has_error()27 		bool has_error() { return msg.has_error; }
has_warning()28 		bool has_warning() { return msg.has_warning; }
getWarnings()29 		std::string getWarnings() { return msg.getWarnings(); }
getError()30 		std::string getError() { return msg.getError(); }
31 
32 		std::vector<SpatRaster> ds;
SpatRasterCollection()33 		SpatRasterCollection() {};
SpatRasterCollection(size_t n)34 		SpatRasterCollection(size_t n) { ds.resize(n); };
size()35 		size_t size() { return ds.size(); }
resize(size_t n)36 		void resize(size_t n) { ds.resize(n); }
push_back(SpatRaster r)37 		void push_back(SpatRaster r) { ds.push_back(r); };
erase(size_t i)38 		void erase(size_t i) {
39 			if (i < ds.size()) {
40 				ds.erase(ds.begin()+i);
41 			}
42 		}
43 		SpatRaster merge(SpatOptions &opt);
44 		SpatRaster mosaic(std::string fun, SpatOptions &opt);
45 		SpatRaster summary(std::string fun, SpatOptions &opt);
46 
47 };
48 
49 // A class for "sub-datasets"
50 class SpatRasterStack {
51 	public:
52 		SpatMessages msg;
setError(std::string s)53 		void setError(std::string s) { msg.setError(s); }
addWarning(std::string s)54 		void addWarning(std::string s) { msg.addWarning(s); }
has_error()55 		bool has_error() { return msg.has_error; }
has_warning()56 		bool has_warning() { return msg.has_warning; }
getWarnings()57 		std::string getWarnings() { return msg.getWarnings();}
getError()58 		std::string getError() { return msg.getError();}
59 
60 		std::vector<SpatRaster> ds;
61 		std::vector<std::string> names;
62 		std::vector<std::string> long_names;
63 		std::vector<std::string> units;
SpatRasterStack()64 		SpatRasterStack() {};
65 		SpatRasterStack(std::string fname, std::vector<int> ids, bool useids);
66 		SpatRasterStack(SpatRaster r, std::string name, std::string longname, std::string unit, bool warn=false) {
67 			push_back(r, name, longname, unit, warn);
68 		};
69 
70 		std::vector<std::vector<std::vector<double>>> extractXY(std::vector<double> &x, std::vector<double> &y, std::string method);
71 		std::vector<std::vector<std::vector<double>>> extractCell(std::vector<double> &cell);
72 		std::vector<std::vector<std::vector<std::vector<double>>>> extractVector(SpatVector v, bool touches, std::string method, SpatOptions &opt);
73 
get_names()74 		std::vector<std::string> get_names() {
75 			return names;
76 		};
set_names(std::vector<std::string> nms)77 		void set_names(std::vector<std::string> nms) {
78 			if (nms.size() == ds.size()) {
79 				names = nms;
80 			}
81 		}
get_longnames()82 		std::vector<std::string> get_longnames() {
83 			return long_names;
84 		};
set_longnames(std::vector<std::string> nms)85 		void set_longnames(std::vector<std::string> nms) {
86 			if (nms.size() == ds.size()) {
87 				long_names = nms;
88 			}
89 		}
get_units()90 		std::vector<std::string> get_units() {
91 			return units;
92 		};
set_units(std::vector<std::string> u)93 		void set_units(std::vector<std::string> u) {
94 			if (u.size() == ds.size()) {
95 				units = u;
96 			}
97 		}
98 
readStart()99 		bool readStart() {
100 			for (auto& x : ds) { if (!x.readStart()) return false; }
101 			return true;
102 		}
103 
readStop()104 		bool readStop() {
105 			for (auto& x : ds) { if (!x.readStop()) return false; }
106 			return true;
107 		}
108 
nsds()109 		unsigned nsds() {
110 			return ds.size();
111 		}
nrow()112 		unsigned nrow() {
113 			if (ds.size() > 0) {
114 				return ds[0].nrow();
115 			} else {
116 				return 0;
117 			}
118 		}
ncol()119 		unsigned ncol() {
120 			if (ds.size() > 0) {
121 				return ds[0].ncol();
122 			} else {
123 				return 0;
124 			}
125 		}
126 
nlyr()127 		std::vector<unsigned> nlyr() {
128 			std::vector<unsigned> out;
129 			if (ds.size() > 0) {
130 				out.reserve(ds.size());
131 				for (size_t i=0; i<ds.size(); i++) {
132 					out.push_back(ds[i].nlyr());
133 				}
134 			}
135 			return out;
136 		}
137 
getSRS(std::string s)138 		std::string getSRS(std::string s) {
139 			if (ds.size() > 0) {
140 				return ds[0].getSRS(s);
141 			} else {
142 				return "";
143 			}
144 		}
145 
push_back(SpatRaster r,std::string name,std::string longname,std::string unit,bool warn)146 		bool push_back(SpatRaster r, std::string name, std::string longname, std::string unit, bool warn) {
147 			if (ds.size() > 0) {
148 				if (!r.compare_geom(ds[0], false, false, true, true, true, false)) {
149 //				if (!ds[0].compare_geom(r, false, false, true, true, false, false)) {
150 					if (warn) {
151 						addWarning(r.msg.getError() +" (" + name + ")");
152 						return true;
153 					} else {
154 						setError(r.msg.getError() +" (" + name + ")");
155 						return false;
156 					}
157 				}
158 			}
159 			ds.push_back(r);
160 			names.push_back(name);
161 			long_names.push_back(longname);
162 			units.push_back(unit);
163 			return true;
164 		};
165 
size()166 		size_t size() { return ds.size(); }
resize(size_t n)167 		void resize(size_t n) {
168 			if (n < ds.size()) {
169 				ds.resize(n);
170 				names.resize(n);
171 				long_names.resize(n);
172 				units.resize(n);
173 			}
174 		}
erase(size_t i)175 		void erase(size_t i) {
176 			if (i < ds.size()) {
177 				ds.erase(ds.begin()+i);
178 				names.erase(names.begin()+i);
179 				long_names.erase(long_names.begin()+i);
180 				units.erase(units.begin()+i);
181 			}
182 		}
183 
184 
getsds(size_t i)185 		SpatRaster getsds(size_t i) {
186 			if (i < ds.size()) {
187 				return(ds[i]);
188 			} else {
189 				SpatRaster out;
190 				out.setError("invalid index");
191 				return out;
192 			}
193 		}
subset(std::vector<unsigned> x)194 		SpatRasterStack subset(std::vector<unsigned> x) {
195 			SpatRasterStack out;
196 			for (size_t i=0; i<x.size(); i++) {
197 				if (x[i] < ds.size()) {
198 					out.push_back(ds[x[i]], names[i], long_names[i], units[i], true);
199 				}
200 			}
201 			return out;
202 		}
203 
replace(unsigned i,SpatRaster x)204 		void replace(unsigned i, SpatRaster x) {
205 			if (i > (ds.size()-1)) {
206 				setError("invalid index");
207 				return;
208 			}
209 			if (ds.size() == 0) {
210 				setError("cannot replace on empty stack");
211 				return;
212 			}
213 			if (!ds[0].compare_geom(x, false, false, true, true, false, false)) {
214 				setError("extent does not match");
215 				return;
216 			}
217 
218 			ds[i] = x;
219 			names[i] = x.getNames()[0];
220 			long_names[i] = x.getLongSourceNames()[0];
221 			units[i] = x.getUnit()[0];
222 		}
223 
collapse()224 		SpatRaster collapse() {
225 			SpatRaster out;
226 
227 			if (ds.size() > 0) {
228 				out = ds[0];
229 				for (size_t i=1; i<ds.size(); i++) {
230 					for (size_t j=0; j<ds[i].source.size(); j++) {
231 						out.source.push_back(ds[i].source[j]);
232 					}
233 				}
234 			}
235 			return out;
236 		}
237 
238 		SpatRaster summary_numb(std::string fun, std::vector<double> add, bool narm, SpatOptions &opt);
239 		SpatRaster summary(std::string fun, bool narm, SpatOptions &opt);
240 };
241 
242 
243