Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PDS 4 Driver; Planetary Data System Format
4 : * Purpose: Implementation of PDS4Dataset
5 : * Author: Even Rouault, even.rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2019, Hobu Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #pragma once
14 :
15 : #include "cpl_string.h"
16 : #include "gdal_priv.h"
17 : #include "gdal_proxy.h"
18 : #include "ogreditablelayer.h"
19 : #include "rawdataset.h"
20 : #include "ogr_spatialref.h"
21 :
22 : #include <array>
23 : #include <vector>
24 :
25 : class PDS4Dataset;
26 :
27 : /************************************************************************/
28 : /* ==================================================================== */
29 : /* PDS4TableBaseLayer */
30 : /* ==================================================================== */
31 : /************************************************************************/
32 :
33 : class PDS4TableBaseLayer CPL_NON_FINAL : public OGRLayer
34 : {
35 : protected:
36 : PDS4Dataset *m_poDS = nullptr;
37 : OGRFeatureDefn *m_poRawFeatureDefn = nullptr;
38 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
39 : CPLString m_osFilename{};
40 : int m_iLatField = -1;
41 : int m_iLongField = -1;
42 : int m_iAltField = -1;
43 : int m_iWKT = -1;
44 : bool m_bKeepGeomColmuns = false;
45 : bool m_bDirtyHeader = false;
46 : VSILFILE *m_fp = nullptr;
47 : GIntBig m_nFeatureCount = -1;
48 : GIntBig m_nFID = 1;
49 : vsi_l_offset m_nOffset = 0;
50 : CPLStringList m_aosLCO{};
51 : std::string m_osLineEnding{};
52 :
53 : void SetupGeomField();
54 : OGRFeature *AddGeometryFromFields(OGRFeature *poFeature);
55 : OGRFeature *AddFieldsFromGeometry(OGRFeature *poFeature);
56 : void MarkHeaderDirty();
57 : CPLXMLNode *RefreshFileAreaObservationalBeginningCommon(
58 : CPLXMLNode *psFAO, const CPLString &osPrefix,
59 : const char *pszTableEltName, CPLString &osDescription);
60 : void ParseLineEndingOption(CSLConstList papszOptions);
61 :
62 : CPL_DISALLOW_COPY_ASSIGN(PDS4TableBaseLayer)
63 :
64 : public:
65 : PDS4TableBaseLayer(PDS4Dataset *poDS, const char *pszName,
66 : const char *pszFilename);
67 : ~PDS4TableBaseLayer() override;
68 :
69 : using OGRLayer::GetLayerDefn;
70 :
71 1805 : const OGRFeatureDefn *GetLayerDefn() const override
72 : {
73 1805 : return m_poFeatureDefn;
74 : }
75 :
76 : GIntBig GetFeatureCount(int bForce) override;
77 :
78 136 : const char *GetFileName() const
79 : {
80 136 : return m_osFilename.c_str();
81 : }
82 :
83 72 : bool IsDirtyHeader() const
84 : {
85 72 : return m_bDirtyHeader;
86 : }
87 :
88 69 : int GetRawFieldCount() const
89 : {
90 69 : return m_poRawFeatureDefn->GetFieldCount();
91 : }
92 :
93 : bool RenameFileTo(const char *pszNewName);
94 : virtual char **GetFileList() const;
95 :
96 : virtual void RefreshFileAreaObservational(CPLXMLNode *psFAO) = 0;
97 :
98 : GDALDataset *GetDataset() override;
99 : };
100 :
101 : /************************************************************************/
102 : /* ==================================================================== */
103 : /* PDS4FixedWidthTable */
104 : /* ==================================================================== */
105 : /************************************************************************/
106 :
107 : template <class T> class PDS4EditableSynchronizer;
108 :
109 : class PDS4FixedWidthTable CPL_NON_FINAL : public PDS4TableBaseLayer
110 : {
111 : friend class PDS4EditableSynchronizer<PDS4FixedWidthTable>;
112 :
113 : protected:
114 : int m_nRecordSize = 0;
115 : CPLString m_osBuffer{};
116 :
117 : struct Field
118 : {
119 : int m_nOffset = 0; // in XML 1-based, here 0-based
120 : int m_nLength = 0;
121 : CPLString m_osDataType{};
122 : CPLString m_osUnit{};
123 : CPLString m_osDescription{};
124 : CPLString m_osSpecialConstantsXML{};
125 : };
126 :
127 : std::vector<Field> m_aoFields{};
128 :
129 : virtual CPLString GetSubType() const = 0;
130 :
131 : virtual bool CreateFieldInternal(OGRFieldType eType,
132 : OGRFieldSubType eSubType, int nWidth,
133 : Field &f) = 0;
134 :
135 : bool ReadFields(const CPLXMLNode *psParent, int nBaseOffset,
136 : const CPLString &osSuffixFieldName);
137 :
138 : public:
139 : PDS4FixedWidthTable(PDS4Dataset *poDS, const char *pszName,
140 : const char *pszFilename);
141 :
142 : void ResetReading() override;
143 : OGRFeature *GetFeature(GIntBig nFID) override;
144 : OGRFeature *GetNextFeature() override;
145 : int TestCapability(const char *) const override;
146 : OGRErr ISetFeature(OGRFeature *poFeature) override;
147 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
148 : OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override;
149 :
150 : bool ReadTableDef(const CPLXMLNode *psTable);
151 :
152 : bool InitializeNewLayer(const OGRSpatialReference *poSRS,
153 : bool bForceGeographic, OGRwkbGeometryType eGType,
154 : const char *const *papszOptions);
155 :
156 : virtual PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS,
157 : const char *pszName,
158 : const char *pszFilename) = 0;
159 :
160 : void RefreshFileAreaObservational(CPLXMLNode *psFAO) override;
161 : };
162 :
163 : /************************************************************************/
164 : /* ==================================================================== */
165 : /* PDS4TableCharacter */
166 : /* ==================================================================== */
167 : /************************************************************************/
168 :
169 : class PDS4TableCharacter final : public PDS4FixedWidthTable
170 : {
171 565 : CPLString GetSubType() const override
172 : {
173 565 : return "Character";
174 : }
175 :
176 : bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType,
177 : int nWidth, Field &f) override;
178 :
179 : public:
180 : PDS4TableCharacter(PDS4Dataset *poDS, const char *pszName,
181 : const char *pszFilename);
182 :
183 2 : PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
184 : const char *pszFilename) override
185 : {
186 2 : return new PDS4TableCharacter(poDS, pszName, pszFilename);
187 : }
188 : };
189 :
190 : /************************************************************************/
191 : /* ==================================================================== */
192 : /* PDS4TableBinary */
193 : /* ==================================================================== */
194 : /************************************************************************/
195 :
196 : class PDS4TableBinary final : public PDS4FixedWidthTable
197 : {
198 3258 : CPLString GetSubType() const override
199 : {
200 3258 : return "Binary";
201 : }
202 :
203 : bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType,
204 : int nWidth, Field &f) override;
205 :
206 : public:
207 : PDS4TableBinary(PDS4Dataset *poDS, const char *pszName,
208 : const char *pszFilename);
209 :
210 0 : PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
211 : const char *pszFilename) override
212 : {
213 0 : return new PDS4TableBinary(poDS, pszName, pszFilename);
214 : }
215 : };
216 :
217 : /************************************************************************/
218 : /* ==================================================================== */
219 : /* PDS4DelimitedTable */
220 : /* ==================================================================== */
221 : /************************************************************************/
222 :
223 : class PDS4DelimitedTable CPL_NON_FINAL : public PDS4TableBaseLayer
224 : {
225 : friend class PDS4EditableSynchronizer<PDS4DelimitedTable>;
226 :
227 : protected:
228 : bool m_bCreation = false;
229 : char m_chFieldDelimiter = ',';
230 : bool m_bAddWKTColumnPending = false;
231 :
232 : struct Field
233 : {
234 : CPLString m_osDataType{};
235 : CPLString m_osUnit{};
236 : CPLString m_osDescription{};
237 : CPLString m_osSpecialConstantsXML{};
238 : CPLString m_osMissingConstant{}; // included in above potentially
239 : };
240 :
241 : std::vector<Field> m_aoFields{};
242 :
243 : OGRFeature *GetNextFeatureRaw();
244 : CPLString QuoteIfNeeded(const char *pszVal);
245 : void GenerateVRT();
246 :
247 : bool ReadFields(const CPLXMLNode *psParent,
248 : const CPLString &osSuffixFieldName);
249 :
250 : public:
251 : PDS4DelimitedTable(PDS4Dataset *poDS, const char *pszName,
252 : const char *pszFilename);
253 : ~PDS4DelimitedTable() override;
254 :
255 : void ResetReading() override;
256 : OGRFeature *GetNextFeature() override;
257 : int TestCapability(const char *) const override;
258 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
259 : OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override;
260 :
261 : bool ReadTableDef(const CPLXMLNode *psTable);
262 :
263 : bool InitializeNewLayer(const OGRSpatialReference *poSRS,
264 : bool bForceGeographic, OGRwkbGeometryType eGType,
265 : const char *const *papszOptions);
266 :
267 : void RefreshFileAreaObservational(CPLXMLNode *psFAO) override;
268 : char **GetFileList() const override;
269 :
270 1 : PDS4DelimitedTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
271 : const char *pszFilename)
272 : {
273 1 : return new PDS4DelimitedTable(poDS, pszName, pszFilename);
274 : }
275 : };
276 :
277 : /************************************************************************/
278 : /* ==================================================================== */
279 : /* PDS4EditableLayer */
280 : /* ==================================================================== */
281 : /************************************************************************/
282 :
283 324 : class PDS4EditableLayer final : public OGREditableLayer
284 : {
285 : PDS4TableBaseLayer *GetBaseLayer() const;
286 :
287 : public:
288 : explicit PDS4EditableLayer(
289 : std::unique_ptr<PDS4FixedWidthTable> poBaseLayer);
290 : explicit PDS4EditableLayer(std::unique_ptr<PDS4DelimitedTable> poBaseLayer);
291 : ~PDS4EditableLayer() override;
292 :
293 69 : void RefreshFileAreaObservational(CPLXMLNode *psFAO)
294 : {
295 69 : GetBaseLayer()->RefreshFileAreaObservational(psFAO);
296 69 : }
297 :
298 69 : const char *GetFileName() const
299 : {
300 69 : return GetBaseLayer()->GetFileName();
301 : }
302 :
303 72 : bool IsDirtyHeader() const
304 : {
305 72 : return GetBaseLayer()->IsDirtyHeader();
306 : }
307 :
308 69 : int GetRawFieldCount() const
309 : {
310 69 : return GetBaseLayer()->GetRawFieldCount();
311 : }
312 :
313 : void SetSpatialRef(OGRSpatialReference *poSRS);
314 :
315 64 : char **GetFileList() const
316 : {
317 64 : return GetBaseLayer()->GetFileList();
318 : }
319 : };
320 :
321 : /************************************************************************/
322 : /* PDS4Dataset */
323 : /************************************************************************/
324 :
325 : class PDS4Dataset final : public RawDataset
326 : {
327 : friend class PDS4RawRasterBand;
328 : friend class PDS4WrapperRasterBand;
329 :
330 : VSILFILE *m_fpImage = nullptr;
331 : vsi_l_offset m_nBaseOffset = 0;
332 : GDALDataset *m_poExternalDS = nullptr; // external dataset (GeoTIFF)
333 : OGRSpatialReference m_oSRS{};
334 : bool m_bGotTransform = false;
335 : GDALGeoTransform m_gt{};
336 : CPLString m_osXMLFilename{};
337 : CPLString m_osImageFilename{};
338 : CPLString m_osUnits{};
339 : bool m_bCreatedFromExistingBinaryFile = false;
340 :
341 : std::vector<std::unique_ptr<PDS4EditableLayer>> m_apoLayers{};
342 :
343 : // Write dedicated parameters
344 : bool m_bMustInitImageFile = false;
345 : bool m_bUseSrcLabel = true;
346 : bool m_bDirtyHeader = false;
347 : bool m_bCreateHeader = false;
348 : bool m_bStripFileAreaObservationalFromTemplate = false;
349 : bool m_bIsLSB = true;
350 : CPLString m_osHeaderParsingStandard{};
351 : CPLString m_osInterleave{};
352 : char **m_papszCreationOptions = nullptr;
353 : CPLString m_osXMLPDS4{};
354 :
355 : void CreateHeader(CPLXMLNode *psProduct, const char *pszCARTVersion);
356 : void WriteHeader();
357 : void WriteHeaderAppendCase();
358 : void WriteVectorLayers(CPLXMLNode *psProduct);
359 : void WriteArray(const CPLString &osPrefix, CPLXMLNode *psFAO,
360 : const char *pszLocalIdentifier,
361 : CPLXMLNode *psTemplateSpecialConstants);
362 : void WriteGeoreferencing(CPLXMLNode *psCart, const char *pszCARTVersion);
363 : void ReadGeoreferencing(CPLXMLNode *psProduct);
364 : bool InitImageFile();
365 :
366 : void SubstituteVariables(CPLXMLNode *psNode, char **papszDict);
367 :
368 : bool OpenTableCharacter(const char *pszFilename, const CPLXMLNode *psTable);
369 :
370 : bool OpenTableBinary(const char *pszFilename, const CPLXMLNode *psTable);
371 :
372 : bool OpenTableDelimited(const char *pszFilename, const CPLXMLNode *psTable);
373 :
374 : static std::unique_ptr<PDS4Dataset>
375 : CreateInternal(const char *pszFilename, GDALDataset *poSrcDS, int nXSize,
376 : int nYSize, int nBands, GDALDataType eType,
377 : const char *const *papszOptions);
378 :
379 : CPLErr Close() override;
380 :
381 : CPL_DISALLOW_COPY_ASSIGN(PDS4Dataset)
382 :
383 : public:
384 : PDS4Dataset();
385 : ~PDS4Dataset() override;
386 :
387 : int CloseDependentDatasets() override;
388 :
389 : const OGRSpatialReference *GetSpatialRef() const override;
390 : CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
391 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
392 : CPLErr SetGeoTransform(const GDALGeoTransform >) override;
393 : char **GetFileList() override;
394 : CPLErr SetMetadata(char **papszMD, const char *pszDomain = "") override;
395 :
396 1066 : int GetLayerCount() const override
397 : {
398 1066 : return static_cast<int>(m_apoLayers.size());
399 : }
400 :
401 : using GDALDataset::GetLayer;
402 : const OGRLayer *GetLayer(int) const override;
403 :
404 : OGRLayer *ICreateLayer(const char *pszName,
405 : const OGRGeomFieldDefn *poGeomFieldDefn,
406 : CSLConstList papszOptions) override;
407 :
408 : int TestCapability(const char *pszCap) const override;
409 :
410 : bool GetRawBinaryLayout(GDALDataset::RawBinaryLayout &) override;
411 :
412 : static std::unique_ptr<PDS4Dataset> OpenInternal(GDALOpenInfo *);
413 :
414 187 : static GDALDataset *Open(GDALOpenInfo *poOpenInfo)
415 : {
416 187 : return OpenInternal(poOpenInfo).release();
417 : }
418 :
419 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
420 : int nBands, GDALDataType eType,
421 : char **papszOptions);
422 : static GDALDataset *CreateCopy(const char *pszFilename,
423 : GDALDataset *poSrcDS, int bStrict,
424 : char **papszOptions,
425 : GDALProgressFunc pfnProgress,
426 : void *pProgressData);
427 : static CPLErr Delete(const char *pszName);
428 :
429 263 : const char *const *GetOpenOptions() const
430 : {
431 263 : return papszOpenOptions;
432 : }
433 :
434 338 : void MarkHeaderDirty()
435 : {
436 338 : m_bDirtyHeader = true;
437 338 : }
438 : };
439 :
440 : /************************************************************************/
441 : /* ==================================================================== */
442 : /* PDS4RawRasterBand */
443 : /* ==================================================================== */
444 : /************************************************************************/
445 :
446 : class PDS4RawRasterBand final : public RawRasterBand
447 : {
448 : friend class PDS4Dataset;
449 :
450 : bool m_bHasOffset{};
451 : bool m_bHasScale{};
452 : bool m_bHasNoData{};
453 : bool m_bHasNoDataInt64{};
454 : bool m_bHasNoDataUInt64{};
455 : double m_dfOffset{};
456 : double m_dfScale{};
457 : double m_dfNoData{};
458 : int64_t m_nNoDataInt64{};
459 : uint64_t m_nNoDataUInt64{};
460 :
461 : public:
462 : PDS4RawRasterBand(GDALDataset *l_poDS, int l_nBand, VSILFILE *l_fpRaw,
463 : vsi_l_offset l_nImgOffset, int l_nPixelOffset,
464 : int l_nLineOffset, GDALDataType l_eDataType,
465 : RawRasterBand::ByteOrder eByteOrderIn);
466 :
467 : CPLErr IWriteBlock(int, int, void *) override;
468 :
469 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
470 : GDALDataType, GSpacing nPixelSpace, GSpacing nLineSpace,
471 : GDALRasterIOExtraArg *psExtraArg) override;
472 :
473 : double GetOffset(int *pbSuccess = nullptr) override;
474 : double GetScale(int *pbSuccess = nullptr) override;
475 : CPLErr SetOffset(double dfNewOffset) override;
476 : CPLErr SetScale(double dfNewScale) override;
477 : double GetNoDataValue(int *pbSuccess = nullptr) override;
478 : CPLErr SetNoDataValue(double dfNewNoData) override;
479 : int64_t GetNoDataValueAsInt64(int *pbSuccess = nullptr) override;
480 : uint64_t GetNoDataValueAsUInt64(int *pbSuccess = nullptr) override;
481 : CPLErr SetNoDataValueAsInt64(int64_t nNoData) override;
482 : CPLErr SetNoDataValueAsUInt64(uint64_t nNoData) override;
483 :
484 125 : const char *GetUnitType() override
485 : {
486 125 : return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
487 : }
488 :
489 67 : CPLErr SetUnitType(const char *pszUnits) override
490 : {
491 67 : static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
492 67 : return CE_None;
493 : }
494 :
495 : void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
496 : };
497 :
498 : /************************************************************************/
499 : /* ==================================================================== */
500 : /* PDS4WrapperRasterBand */
501 : /* */
502 : /* proxy for bands stored in other formats. */
503 : /* ==================================================================== */
504 : /************************************************************************/
505 : class PDS4WrapperRasterBand final : public GDALProxyRasterBand
506 : {
507 : friend class PDS4Dataset;
508 :
509 : GDALRasterBand *m_poBaseBand{};
510 : bool m_bHasOffset{};
511 : bool m_bHasScale{};
512 : bool m_bHasNoData{};
513 : bool m_bHasNoDataInt64{};
514 : bool m_bHasNoDataUInt64{};
515 : double m_dfOffset{};
516 : double m_dfScale{};
517 : double m_dfNoData{};
518 : int64_t m_nNoDataInt64{};
519 : uint64_t m_nNoDataUInt64{};
520 :
521 : CPL_DISALLOW_COPY_ASSIGN(PDS4WrapperRasterBand)
522 :
523 : protected:
524 : virtual GDALRasterBand *
525 161 : RefUnderlyingRasterBand(bool /*bForceOpen*/) const override
526 : {
527 161 : return m_poBaseBand;
528 : }
529 :
530 : public:
531 : explicit PDS4WrapperRasterBand(GDALRasterBand *poBaseBandIn);
532 :
533 : virtual CPLErr Fill(double dfRealValue,
534 : double dfImaginaryValue = 0) override;
535 : CPLErr IWriteBlock(int, int, void *) override;
536 :
537 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
538 : GDALDataType, GSpacing nPixelSpace, GSpacing nLineSpace,
539 : GDALRasterIOExtraArg *psExtraArg) override;
540 :
541 : double GetOffset(int *pbSuccess = nullptr) override;
542 : double GetScale(int *pbSuccess = nullptr) override;
543 : CPLErr SetOffset(double dfNewOffset) override;
544 : CPLErr SetScale(double dfNewScale) override;
545 : double GetNoDataValue(int *pbSuccess = nullptr) override;
546 : CPLErr SetNoDataValue(double dfNewNoData) override;
547 : int64_t GetNoDataValueAsInt64(int *pbSuccess = nullptr) override;
548 : uint64_t GetNoDataValueAsUInt64(int *pbSuccess = nullptr) override;
549 : CPLErr SetNoDataValueAsInt64(int64_t nNoData) override;
550 : CPLErr SetNoDataValueAsUInt64(uint64_t nNoData) override;
551 :
552 18 : const char *GetUnitType() override
553 : {
554 18 : return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
555 : }
556 :
557 15 : CPLErr SetUnitType(const char *pszUnits) override
558 : {
559 15 : static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
560 15 : return CE_None;
561 : }
562 :
563 0 : int GetMaskFlags() override
564 : {
565 0 : return nMaskFlags;
566 : }
567 :
568 0 : GDALRasterBand *GetMaskBand() override
569 : {
570 0 : return poMask;
571 : }
572 :
573 : void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
574 : };
575 :
576 : /************************************************************************/
577 : /* ==================================================================== */
578 : /* PDS4MaskBand */
579 : /* ==================================================================== */
580 :
581 : class PDS4MaskBand final : public GDALRasterBand
582 : {
583 : GDALRasterBand *m_poBaseBand{};
584 : void *m_pBuffer{};
585 : std::vector<double> m_adfConstants{};
586 :
587 : CPL_DISALLOW_COPY_ASSIGN(PDS4MaskBand)
588 :
589 : public:
590 : PDS4MaskBand(GDALRasterBand *poBaseBand,
591 : const std::vector<double> &adfConstants);
592 : ~PDS4MaskBand() override;
593 :
594 : CPLErr IReadBlock(int, int, void *) override;
595 : };
|