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 2703 : OGRFeatureDefn *GetLayerDefn() override
67 : {
68 2703 : 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 324 : class PDS4EditableLayer final : public OGREditableLayer
279 : {
280 : PDS4TableBaseLayer *GetBaseLayer() const;
281 :
282 : public:
283 : explicit PDS4EditableLayer(PDS4FixedWidthTable *poBaseLayer);
284 : explicit PDS4EditableLayer(PDS4DelimitedTable *poBaseLayer);
285 : ~PDS4EditableLayer() override;
286 :
287 69 : void RefreshFileAreaObservational(CPLXMLNode *psFAO)
288 : {
289 69 : GetBaseLayer()->RefreshFileAreaObservational(psFAO);
290 69 : }
291 :
292 69 : const char *GetFileName() const
293 : {
294 69 : return GetBaseLayer()->GetFileName();
295 : }
296 :
297 72 : bool IsDirtyHeader() const
298 : {
299 72 : return GetBaseLayer()->IsDirtyHeader();
300 : }
301 :
302 69 : int GetRawFieldCount() const
303 : {
304 69 : return GetBaseLayer()->GetRawFieldCount();
305 : }
306 :
307 : void SetSpatialRef(OGRSpatialReference *poSRS);
308 :
309 64 : char **GetFileList() const
310 : {
311 64 : return GetBaseLayer()->GetFileList();
312 : }
313 : };
314 :
315 : /************************************************************************/
316 : /* PDS4Dataset */
317 : /************************************************************************/
318 :
319 : class PDS4Dataset final : public RawDataset
320 : {
321 : friend class PDS4RawRasterBand;
322 : friend class PDS4WrapperRasterBand;
323 :
324 : VSILFILE *m_fpImage = nullptr;
325 : vsi_l_offset m_nBaseOffset = 0;
326 : GDALDataset *m_poExternalDS = nullptr; // external dataset (GeoTIFF)
327 : OGRSpatialReference m_oSRS{};
328 : bool m_bGotTransform = false;
329 : double m_adfGeoTransform[6];
330 : CPLString m_osXMLFilename{};
331 : CPLString m_osImageFilename{};
332 : CPLString m_osUnits{};
333 : bool m_bCreatedFromExistingBinaryFile = false;
334 :
335 : std::vector<std::unique_ptr<PDS4EditableLayer>> m_apoLayers{};
336 :
337 : // Write dedicated parameters
338 : bool m_bMustInitImageFile = false;
339 : bool m_bUseSrcLabel = true;
340 : bool m_bDirtyHeader = false;
341 : bool m_bCreateHeader = false;
342 : bool m_bStripFileAreaObservationalFromTemplate = false;
343 : bool m_bIsLSB = true;
344 : CPLString m_osHeaderParsingStandard{};
345 : CPLString m_osInterleave{};
346 : char **m_papszCreationOptions = nullptr;
347 : CPLString m_osXMLPDS4{};
348 :
349 : void CreateHeader(CPLXMLNode *psProduct, const char *pszCARTVersion);
350 : void WriteHeader();
351 : void WriteHeaderAppendCase();
352 : void WriteVectorLayers(CPLXMLNode *psProduct);
353 : void WriteArray(const CPLString &osPrefix, CPLXMLNode *psFAO,
354 : const char *pszLocalIdentifier,
355 : CPLXMLNode *psTemplateSpecialConstants);
356 : void WriteGeoreferencing(CPLXMLNode *psCart, const char *pszCARTVersion);
357 : void ReadGeoreferencing(CPLXMLNode *psProduct);
358 : bool InitImageFile();
359 :
360 : void SubstituteVariables(CPLXMLNode *psNode, char **papszDict);
361 :
362 : bool OpenTableCharacter(const char *pszFilename, const CPLXMLNode *psTable);
363 :
364 : bool OpenTableBinary(const char *pszFilename, const CPLXMLNode *psTable);
365 :
366 : bool OpenTableDelimited(const char *pszFilename, const CPLXMLNode *psTable);
367 :
368 : static PDS4Dataset *CreateInternal(const char *pszFilename,
369 : GDALDataset *poSrcDS, int nXSize,
370 : int nYSize, int nBands,
371 : GDALDataType eType,
372 : const char *const *papszOptions);
373 :
374 : CPLErr Close() override;
375 :
376 : public:
377 : PDS4Dataset();
378 : virtual ~PDS4Dataset();
379 :
380 : virtual int CloseDependentDatasets() override;
381 :
382 : const OGRSpatialReference *GetSpatialRef() const override;
383 : CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
384 : virtual CPLErr GetGeoTransform(double *) override;
385 : virtual CPLErr SetGeoTransform(double *) override;
386 : virtual char **GetFileList() override;
387 : virtual CPLErr SetMetadata(char **papszMD,
388 : const char *pszDomain = "") override;
389 :
390 1013 : int GetLayerCount() override
391 : {
392 1013 : return static_cast<int>(m_apoLayers.size());
393 : }
394 :
395 : OGRLayer *GetLayer(int) override;
396 :
397 : OGRLayer *ICreateLayer(const char *pszName,
398 : const OGRGeomFieldDefn *poGeomFieldDefn,
399 : CSLConstList papszOptions) override;
400 :
401 : int TestCapability(const char *pszCap) override;
402 :
403 : bool GetRawBinaryLayout(GDALDataset::RawBinaryLayout &) override;
404 :
405 : static PDS4Dataset *OpenInternal(GDALOpenInfo *);
406 :
407 179 : static GDALDataset *Open(GDALOpenInfo *poOpenInfo)
408 : {
409 179 : return OpenInternal(poOpenInfo);
410 : }
411 :
412 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
413 : int nBands, GDALDataType eType,
414 : char **papszOptions);
415 : static GDALDataset *CreateCopy(const char *pszFilename,
416 : GDALDataset *poSrcDS, int bStrict,
417 : char **papszOptions,
418 : GDALProgressFunc pfnProgress,
419 : void *pProgressData);
420 : static CPLErr Delete(const char *pszName);
421 :
422 262 : const char *const *GetOpenOptions() const
423 : {
424 262 : return papszOpenOptions;
425 : }
426 :
427 338 : void MarkHeaderDirty()
428 : {
429 338 : m_bDirtyHeader = true;
430 338 : }
431 : };
432 :
433 : /************************************************************************/
434 : /* ==================================================================== */
435 : /* PDS4RawRasterBand */
436 : /* ==================================================================== */
437 : /************************************************************************/
438 :
439 : class PDS4RawRasterBand final : public RawRasterBand
440 : {
441 : friend class PDS4Dataset;
442 :
443 : bool m_bHasOffset;
444 : bool m_bHasScale;
445 : bool m_bHasNoData;
446 : double m_dfOffset;
447 : double m_dfScale;
448 : double m_dfNoData;
449 :
450 : public:
451 : PDS4RawRasterBand(GDALDataset *l_poDS, int l_nBand, VSILFILE *l_fpRaw,
452 : vsi_l_offset l_nImgOffset, int l_nPixelOffset,
453 : int l_nLineOffset, GDALDataType l_eDataType,
454 : RawRasterBand::ByteOrder eByteOrderIn);
455 :
456 844 : virtual ~PDS4RawRasterBand()
457 422 : {
458 844 : }
459 :
460 : virtual CPLErr IWriteBlock(int, int, void *) override;
461 :
462 : virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
463 : GDALDataType, GSpacing nPixelSpace,
464 : GSpacing nLineSpace,
465 : GDALRasterIOExtraArg *psExtraArg) override;
466 :
467 : virtual double GetOffset(int *pbSuccess = nullptr) override;
468 : virtual double GetScale(int *pbSuccess = nullptr) override;
469 : virtual CPLErr SetOffset(double dfNewOffset) override;
470 : virtual CPLErr SetScale(double dfNewScale) override;
471 : virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
472 : virtual CPLErr SetNoDataValue(double dfNewNoData) override;
473 :
474 116 : virtual const char *GetUnitType() override
475 : {
476 116 : return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
477 : }
478 :
479 67 : virtual CPLErr SetUnitType(const char *pszUnits) override
480 : {
481 67 : static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
482 67 : return CE_None;
483 : }
484 :
485 : void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
486 : };
487 :
488 : /************************************************************************/
489 : /* ==================================================================== */
490 : /* PDS4WrapperRasterBand */
491 : /* */
492 : /* proxy for bands stored in other formats. */
493 : /* ==================================================================== */
494 : /************************************************************************/
495 : class PDS4WrapperRasterBand final : public GDALProxyRasterBand
496 : {
497 : friend class PDS4Dataset;
498 :
499 : GDALRasterBand *m_poBaseBand;
500 : bool m_bHasOffset;
501 : bool m_bHasScale;
502 : bool m_bHasNoData;
503 : double m_dfOffset;
504 : double m_dfScale;
505 : double m_dfNoData;
506 :
507 : protected:
508 : virtual GDALRasterBand *
509 150 : RefUnderlyingRasterBand(bool /*bForceOpen*/) const override
510 : {
511 150 : return m_poBaseBand;
512 : }
513 :
514 : public:
515 : explicit PDS4WrapperRasterBand(GDALRasterBand *poBaseBandIn);
516 :
517 34 : ~PDS4WrapperRasterBand()
518 17 : {
519 34 : }
520 :
521 : virtual CPLErr Fill(double dfRealValue,
522 : double dfImaginaryValue = 0) override;
523 : virtual CPLErr IWriteBlock(int, int, void *) override;
524 :
525 : virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
526 : GDALDataType, GSpacing nPixelSpace,
527 : GSpacing nLineSpace,
528 : GDALRasterIOExtraArg *psExtraArg) override;
529 :
530 : virtual double GetOffset(int *pbSuccess = nullptr) override;
531 : virtual double GetScale(int *pbSuccess = nullptr) override;
532 : virtual CPLErr SetOffset(double dfNewOffset) override;
533 : virtual CPLErr SetScale(double dfNewScale) override;
534 : virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
535 : virtual CPLErr SetNoDataValue(double dfNewNoData) override;
536 :
537 11 : virtual const char *GetUnitType() override
538 : {
539 11 : return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
540 : }
541 :
542 13 : virtual CPLErr SetUnitType(const char *pszUnits) override
543 : {
544 13 : static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
545 13 : return CE_None;
546 : }
547 :
548 0 : int GetMaskFlags() override
549 : {
550 0 : return nMaskFlags;
551 : }
552 :
553 0 : GDALRasterBand *GetMaskBand() override
554 : {
555 0 : return poMask;
556 : }
557 :
558 : void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
559 : };
560 :
561 : /************************************************************************/
562 : /* ==================================================================== */
563 : /* PDS4MaskBand */
564 : /* ==================================================================== */
565 :
566 : class PDS4MaskBand final : public GDALRasterBand
567 : {
568 : GDALRasterBand *m_poBaseBand;
569 : void *m_pBuffer;
570 : std::vector<double> m_adfConstants;
571 :
572 : public:
573 : PDS4MaskBand(GDALRasterBand *poBaseBand,
574 : const std::vector<double> &adfConstants);
575 : ~PDS4MaskBand();
576 :
577 : virtual CPLErr IReadBlock(int, int, void *) override;
578 : };
|