/src/bag/api/bag_descriptor.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | #include "bag_descriptor.h" |
3 | | #include "bag_exceptions.h" |
4 | | #include "bag_layer.h" |
5 | | #include "bag_metadata.h" |
6 | | |
7 | | #include <algorithm> |
8 | | #include <cctype> |
9 | | |
10 | | |
11 | | namespace BAG { |
12 | | |
13 | | namespace { |
14 | | |
15 | | //! Find a descriptor by layer type and case-insensitive name. |
16 | | /*! |
17 | | \param inDescriptors |
18 | | The descriptors to search. |
19 | | \param inType |
20 | | The layer type to match. |
21 | | \param inName |
22 | | The case-insensitive layer name to match. |
23 | | |
24 | | \return |
25 | | The found descriptor. |
26 | | nullptr if not found. |
27 | | */ |
28 | | const LayerDescriptor* getLayerDescriptor( |
29 | | const std::vector<std::weak_ptr<const LayerDescriptor>>& inDescriptors, |
30 | | LayerType inType, |
31 | | const std::string& inName) |
32 | 239 | { |
33 | 239 | if (inType == Georef_Metadata && inName.empty()) |
34 | 0 | throw NameRequired{}; |
35 | | |
36 | 239 | std::string nameLower{inName}; |
37 | 239 | std::transform(begin(nameLower), end(nameLower), begin(nameLower), |
38 | 2.58k | [](char c) noexcept { |
39 | 2.58k | return static_cast<char>(std::tolower(c)); |
40 | 2.58k | }); |
41 | | |
42 | 239 | const auto& layerDesc = std::find_if(cbegin(inDescriptors), |
43 | 239 | cend(inDescriptors), |
44 | 239 | [inType, &nameLower](const std::weak_ptr<const LayerDescriptor>& d) { |
45 | 112 | if (d.expired()) |
46 | 0 | return false; |
47 | | |
48 | 112 | auto desc = d.lock(); |
49 | | |
50 | 112 | if (desc->getLayerType() != inType) |
51 | 112 | return false; |
52 | | |
53 | 0 | if (nameLower.empty()) |
54 | 0 | return true; |
55 | | |
56 | 0 | std::string foundNameLower{desc->getName()}; |
57 | 0 | std::transform(begin(foundNameLower), end(foundNameLower), begin(foundNameLower), |
58 | 0 | [](char c) noexcept { |
59 | 0 | return static_cast<char>(std::tolower(c)); |
60 | 0 | }); |
61 | |
|
62 | 0 | return foundNameLower == nameLower; |
63 | 0 | }); |
64 | 239 | if (layerDesc == cend(inDescriptors)) |
65 | 239 | return {}; |
66 | | |
67 | 0 | return layerDesc->lock().get(); |
68 | 239 | } |
69 | | |
70 | | } // namespace |
71 | | |
72 | | //! Constructor. |
73 | | /*! |
74 | | \param metadata |
75 | | The metadata. |
76 | | */ |
77 | | Descriptor::Descriptor( |
78 | | const Metadata& metadata) |
79 | 242 | : m_horizontalReferenceSystem(metadata.horizontalReferenceSystemAsWKT()) |
80 | 242 | , m_verticalReferenceSystem(metadata.verticalReferenceSystemAsWKT()) |
81 | 242 | , m_dims({metadata.rows(), metadata.columns()}) |
82 | 242 | , m_projectedCover({metadata.llCornerX(), metadata.llCornerY(), |
83 | 242 | metadata.urCornerX(), metadata.urCornerY()}) |
84 | 242 | , m_origin({metadata.llCornerX(), metadata.llCornerY()}) |
85 | 242 | , m_gridSpacing({metadata.rowResolution(), metadata.columnResolution()}) |
86 | 242 | { |
87 | 242 | } |
88 | | |
89 | | //! Add a layer descriptor to this descriptor. |
90 | | /* |
91 | | \param inDescriptor |
92 | | The layer descriptor. |
93 | | |
94 | | \return |
95 | | The updated descriptor. |
96 | | */ |
97 | | Descriptor& Descriptor::addLayerDescriptor( |
98 | | const LayerDescriptor& inDescriptor) & |
99 | 239 | { |
100 | | // Check if the layer descriptor already exists. |
101 | 239 | if (BAG::getLayerDescriptor(m_layerDescriptors, inDescriptor.getLayerType(), |
102 | 239 | inDescriptor.getName())) |
103 | 0 | throw LayerExists{}; |
104 | | |
105 | 239 | m_layerDescriptors.emplace_back(inDescriptor.shared_from_this()); |
106 | | |
107 | 239 | return *this; |
108 | 239 | } |
109 | | |
110 | | //! Retrieve BAG grid dimensions. |
111 | | /*! |
112 | | \return |
113 | | The rows and columns of the BAG. |
114 | | */ |
115 | | const std::tuple<uint32_t, uint32_t>& Descriptor::getDims() const & noexcept |
116 | 48 | { |
117 | 48 | return m_dims; |
118 | 48 | } |
119 | | |
120 | | //! Retrieve the row and column spacing/resolution of the grid. |
121 | | /* |
122 | | \return |
123 | | The row and column spacing/resolution of the grid. |
124 | | */ |
125 | | const std::tuple<double, double>& Descriptor::getGridSpacing() const & noexcept |
126 | 24 | { |
127 | 24 | return m_gridSpacing; |
128 | 24 | } |
129 | | |
130 | | //! Retrieve the horizontal reference system. |
131 | | /*! |
132 | | \return |
133 | | The horizontal reference system. |
134 | | */ |
135 | | const std::string& Descriptor::getHorizontalReferenceSystem() const & noexcept |
136 | 24 | { |
137 | 24 | return m_horizontalReferenceSystem; |
138 | 24 | } |
139 | | |
140 | | //! Retrieve a list of layer ids. |
141 | | /*! |
142 | | \return |
143 | | A list of layer ids. |
144 | | */ |
145 | | std::vector<uint32_t> Descriptor::getLayerIds() const noexcept |
146 | 0 | { |
147 | 0 | std::vector<uint32_t> ids; |
148 | 0 | ids.reserve(m_layerDescriptors.size()); |
149 | |
|
150 | 0 | for (const auto& desc : m_layerDescriptors) |
151 | 0 | { |
152 | 0 | if (desc.expired()) |
153 | 0 | continue; |
154 | | |
155 | 0 | auto descriptor = desc.lock(); |
156 | 0 | ids.emplace_back(descriptor->getId()); |
157 | 0 | } |
158 | |
|
159 | 0 | return ids; |
160 | 0 | } |
161 | | |
162 | | //! Retrieve the layer descriptor by id. |
163 | | /*! |
164 | | \param id |
165 | | The layer id of the desired layer descriptor. |
166 | | |
167 | | \return |
168 | | The specified layer descriptor. |
169 | | An exception will be thrown if the layer id does not exist. |
170 | | */ |
171 | | const LayerDescriptor& Descriptor::getLayerDescriptor( |
172 | | uint32_t id) const & |
173 | 0 | { |
174 | 0 | const auto& desc = m_layerDescriptors.at(id); |
175 | 0 | if (desc.expired()) |
176 | 0 | throw InvalidLayerDescriptor{}; |
177 | | |
178 | 0 | return *desc.lock(); |
179 | 0 | } |
180 | | |
181 | | //! Retrieve the specified layer descriptor by type and name. |
182 | | /*! |
183 | | \param type |
184 | | The descriptor of the layer specified by type. |
185 | | \param name |
186 | | The case-insensitive name of the layer. |
187 | | Optional for all but georeferenced metadata layers. |
188 | | \return |
189 | | The specified layer descriptor. |
190 | | */ |
191 | | const LayerDescriptor* Descriptor::getLayerDescriptor( |
192 | | LayerType type, |
193 | | const std::string& name) const & |
194 | 0 | { |
195 | 0 | return BAG::getLayerDescriptor(m_layerDescriptors, type, name); |
196 | 0 | } |
197 | | |
198 | | //! Retrieve all the layer descriptors. |
199 | | /*! |
200 | | \return |
201 | | All the layer descriptors. |
202 | | */ |
203 | | const std::vector<std::weak_ptr<const LayerDescriptor>>& |
204 | | Descriptor::getLayerDescriptors() const & noexcept |
205 | 0 | { |
206 | 0 | return m_layerDescriptors; |
207 | 0 | } |
208 | | |
209 | | //! Retrieve all the layer types the descriptor is aware of. |
210 | | /*! |
211 | | \return |
212 | | All the unique layer types the descriptor is aware of. |
213 | | If multiple georeferenced metadata layers are present, the type is only provided once. |
214 | | */ |
215 | | std::vector<LayerType> Descriptor::getLayerTypes() const |
216 | 0 | { |
217 | 0 | std::vector<LayerType> types; |
218 | 0 | types.reserve(m_layerDescriptors.size()); |
219 | |
|
220 | 0 | bool addedGeorefMetadataLayer = false; |
221 | |
|
222 | 0 | for (const auto& desc : m_layerDescriptors) |
223 | 0 | { |
224 | 0 | if (desc.expired()) |
225 | 0 | continue; |
226 | | |
227 | 0 | auto layerDescriptor = desc.lock(); |
228 | |
|
229 | 0 | const auto type = layerDescriptor->getLayerType(); |
230 | 0 | if (type == Georef_Metadata) |
231 | 0 | { |
232 | 0 | if (!addedGeorefMetadataLayer) |
233 | 0 | addedGeorefMetadataLayer = true; |
234 | 0 | else |
235 | 0 | continue; |
236 | 0 | } |
237 | | |
238 | 0 | types.emplace_back(type); |
239 | 0 | } |
240 | |
|
241 | 0 | return types; |
242 | 0 | } |
243 | | |
244 | | //! Retrieve the BAG origin. |
245 | | /*! |
246 | | \return |
247 | | The geographic position of the south west corner of the BAG. |
248 | | */ |
249 | | const std::tuple<double, double>& Descriptor::getOrigin() const & noexcept |
250 | 24 | { |
251 | 24 | return m_origin; |
252 | 24 | } |
253 | | |
254 | | //! Retrieve the projected cover. |
255 | | /*! |
256 | | \return |
257 | | The projected cover of the BAG. |
258 | | The values returned in the tuple are: |
259 | | Lower left corner X, lower left corner Y, upper right corner X, upper right |
260 | | corner Y. |
261 | | */ |
262 | | const std::tuple<double, double, double, double>& |
263 | | Descriptor::getProjectedCover() const & noexcept |
264 | 24 | { |
265 | 24 | return m_projectedCover; |
266 | 24 | } |
267 | | |
268 | | //! Retrieve the BAG version as a string. |
269 | | /*! |
270 | | \return |
271 | | The BAG version as a string. |
272 | | */ |
273 | | const std::string& Descriptor::getVersion() const & noexcept |
274 | 266 | { |
275 | 266 | return m_version; |
276 | 266 | } |
277 | | |
278 | | //! Retrieve the vertical reference system. |
279 | | /*! |
280 | | \return |
281 | | The vertical reference system. |
282 | | */ |
283 | | const std::string& Descriptor::getVerticalReferenceSystem() const & noexcept |
284 | 24 | { |
285 | 24 | return m_verticalReferenceSystem; |
286 | 24 | } |
287 | | |
288 | | //! Retrieve the read only flag value. |
289 | | /*! |
290 | | \return |
291 | | \e true if the BAG is read only. |
292 | | \e false otherwise. |
293 | | */ |
294 | | bool Descriptor::isReadOnly() const noexcept |
295 | 0 | { |
296 | 0 | return m_isReadOnly; |
297 | 0 | } |
298 | | |
299 | | //! Set the BAG grid size. |
300 | | /*! |
301 | | \param rows |
302 | | The number of rows in the BAG. |
303 | | \param columns |
304 | | The number of columns in the BAG. |
305 | | |
306 | | \return |
307 | | The modified descriptor. |
308 | | */ |
309 | | Descriptor& Descriptor::setDims( |
310 | | uint32_t rows, |
311 | | uint32_t columns) & noexcept |
312 | 0 | { |
313 | 0 | m_dims = {rows, columns}; |
314 | 0 | return *this; |
315 | 0 | } |
316 | | |
317 | | //! Set the BAG grid spacing/resolution. |
318 | | /*! |
319 | | \param xSpacing |
320 | | The X spacing/resolution of the BAG grid. |
321 | | \param ySpacing |
322 | | The Y spacing/resolution of the BAG grid. |
323 | | |
324 | | \return |
325 | | The modified descriptor. |
326 | | */ |
327 | | Descriptor& Descriptor::setGridSpacing( |
328 | | double xSpacing, |
329 | | double ySpacing) & noexcept |
330 | 0 | { |
331 | 0 | m_gridSpacing = {xSpacing, ySpacing}; |
332 | 0 | return *this; |
333 | 0 | } |
334 | | |
335 | | //! Set the BAG horizontal reference system. |
336 | | /*! |
337 | | \param horizontalReferenceSystem |
338 | | The new horizontal reference system as WKT. |
339 | | |
340 | | \return |
341 | | The modified descriptor. |
342 | | */ |
343 | | Descriptor& Descriptor::setHorizontalReferenceSystem( |
344 | | const std::string& horizontalReferenceSystem) & noexcept |
345 | 0 | { |
346 | 0 | m_horizontalReferenceSystem = horizontalReferenceSystem; |
347 | 0 | return *this; |
348 | 0 | } |
349 | | |
350 | | //! Set the BAG's origin. |
351 | | /*! |
352 | | \param llX |
353 | | Lower left x value. |
354 | | \param llY |
355 | | Lower left y value. |
356 | | |
357 | | \return |
358 | | The modified descriptor. |
359 | | */ |
360 | | Descriptor& Descriptor::setOrigin( |
361 | | double llX, |
362 | | double llY) & noexcept |
363 | 0 | { |
364 | 0 | m_origin = {llX, llY}; |
365 | 0 | return *this; |
366 | 0 | } |
367 | | |
368 | | //! Set the BAG's projected cover. |
369 | | /*! |
370 | | \param llX |
371 | | Lower left x value. |
372 | | \param llY |
373 | | Lower left y value. |
374 | | \param urX |
375 | | Upper right x value. |
376 | | \param urY |
377 | | Upper right y value. |
378 | | |
379 | | \return |
380 | | The modified descriptor. |
381 | | */ |
382 | | Descriptor& Descriptor::setProjectedCover( |
383 | | double llX, |
384 | | double llY, |
385 | | double urX, |
386 | | double urY) & noexcept |
387 | 0 | { |
388 | 0 | m_projectedCover = {llX, llY, urX, urY}; |
389 | 0 | return *this; |
390 | 0 | } |
391 | | |
392 | | //! Set the BAG's projected cover. |
393 | | /*! |
394 | | \param inReadOnly |
395 | | The new read only flag. |
396 | | \e true enables reading only. |
397 | | \e false allows writing. |
398 | | |
399 | | \return |
400 | | The modified descriptor. |
401 | | */ |
402 | | Descriptor& Descriptor::setReadOnly(bool inReadOnly) & noexcept |
403 | 242 | { |
404 | 242 | m_isReadOnly = inReadOnly; |
405 | 242 | return *this; |
406 | 242 | } |
407 | | |
408 | | //! Set the BAG's version as a string. |
409 | | /*! |
410 | | \param inVersion |
411 | | The new version as a string. |
412 | | |
413 | | \return |
414 | | The modified descriptor. |
415 | | */ |
416 | | Descriptor& Descriptor::setVersion(std::string inVersion) & noexcept |
417 | 242 | { |
418 | 242 | m_version = std::move(inVersion); |
419 | 242 | return *this; |
420 | 242 | } |
421 | | |
422 | | //! Set the BAG's vertical reference system. |
423 | | /*! |
424 | | \param verticalReferenceSystem |
425 | | The new vertical reference system as WKT. |
426 | | |
427 | | \return |
428 | | The modified descriptor. |
429 | | */ |
430 | | Descriptor& Descriptor::setVerticalReferenceSystem( |
431 | | const std::string& verticalReferenceSystem) & noexcept |
432 | 0 | { |
433 | 0 | m_verticalReferenceSystem = verticalReferenceSystem; |
434 | 0 | return *this; |
435 | 0 | } |
436 | | |
437 | | } // namespace BAG |
438 | | |