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