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