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