/src/gdal/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: Idrisi Translator |
4 | | * Purpose: Implements OGRIdrisiDataSource class |
5 | | * Author: Even Rouault, even dot rouault at spatialys.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2011-2012, Even Rouault <even dot rouault at spatialys.com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #include "cpl_conv.h" |
14 | | #include "cpl_string.h" |
15 | | #include "idrisi.h" |
16 | | #include "ogr_idrisi.h" |
17 | | |
18 | | /************************************************************************/ |
19 | | /* OGRIdrisiDataSource() */ |
20 | | /************************************************************************/ |
21 | | |
22 | 15 | OGRIdrisiDataSource::OGRIdrisiDataSource() = default; |
23 | | |
24 | | /************************************************************************/ |
25 | | /* ~OGRIdrisiDataSource() */ |
26 | | /************************************************************************/ |
27 | | |
28 | | OGRIdrisiDataSource::~OGRIdrisiDataSource() |
29 | | |
30 | 15 | { |
31 | 15 | for (int i = 0; i < nLayers; i++) |
32 | 0 | delete papoLayers[i]; |
33 | 15 | CPLFree(papoLayers); |
34 | 15 | } |
35 | | |
36 | | /************************************************************************/ |
37 | | /* GetLayer() */ |
38 | | /************************************************************************/ |
39 | | |
40 | | const OGRLayer *OGRIdrisiDataSource::GetLayer(int iLayer) const |
41 | | |
42 | 0 | { |
43 | 0 | if (iLayer < 0 || iLayer >= nLayers) |
44 | 0 | return nullptr; |
45 | | |
46 | 0 | return papoLayers[iLayer]; |
47 | 0 | } |
48 | | |
49 | | /************************************************************************/ |
50 | | /* Open() */ |
51 | | /************************************************************************/ |
52 | | |
53 | | int OGRIdrisiDataSource::Open(const char *pszFilename) |
54 | | |
55 | 15 | { |
56 | 15 | VSILFILE *fpVCT = VSIFOpenL(pszFilename, "rb"); |
57 | 15 | if (fpVCT == nullptr) |
58 | 0 | return FALSE; |
59 | | |
60 | | // -------------------------------------------------------------------- |
61 | | // Look for .vdc file |
62 | | // -------------------------------------------------------------------- |
63 | 15 | std::string osVDCFilename = CPLResetExtensionSafe(pszFilename, "vdc"); |
64 | 15 | VSILFILE *fpVDC = VSIFOpenL(osVDCFilename.c_str(), "rb"); |
65 | 15 | if (fpVDC == nullptr) |
66 | 15 | { |
67 | 15 | osVDCFilename = CPLResetExtensionSafe(pszFilename, "VDC"); |
68 | 15 | fpVDC = VSIFOpenL(osVDCFilename.c_str(), "rb"); |
69 | 15 | } |
70 | | |
71 | 15 | char **papszVDC = nullptr; |
72 | 15 | if (fpVDC != nullptr) |
73 | 0 | { |
74 | 0 | VSIFCloseL(fpVDC); |
75 | 0 | fpVDC = nullptr; |
76 | |
|
77 | 0 | CPLPushErrorHandler(CPLQuietErrorHandler); |
78 | 0 | papszVDC = CSLLoad2(osVDCFilename.c_str(), 1024, 256, nullptr); |
79 | 0 | CPLPopErrorHandler(); |
80 | 0 | CPLErrorReset(); |
81 | 0 | } |
82 | | |
83 | 15 | OGRwkbGeometryType eType = wkbUnknown; |
84 | | |
85 | 15 | char *pszWTKString = nullptr; |
86 | 15 | if (papszVDC != nullptr) |
87 | 0 | { |
88 | 0 | CSLSetNameValueSeparator(papszVDC, ":"); |
89 | |
|
90 | 0 | const char *pszVersion = CSLFetchNameValue(papszVDC, "file format"); |
91 | |
|
92 | 0 | if (pszVersion == nullptr || !EQUAL(pszVersion, "IDRISI Vector A.1")) |
93 | 0 | { |
94 | 0 | CSLDestroy(papszVDC); |
95 | 0 | VSIFCloseL(fpVCT); |
96 | 0 | return FALSE; |
97 | 0 | } |
98 | | |
99 | 0 | const char *pszRefSystem = CSLFetchNameValue(papszVDC, "ref. system"); |
100 | 0 | const char *pszRefUnits = CSLFetchNameValue(papszVDC, "ref. units"); |
101 | |
|
102 | 0 | if (pszRefSystem != nullptr && pszRefUnits != nullptr) |
103 | 0 | { |
104 | 0 | OGRSpatialReference oSRS; |
105 | 0 | IdrisiGeoReference2Wkt(pszFilename, pszRefSystem, pszRefUnits, |
106 | 0 | oSRS); |
107 | 0 | if (!oSRS.IsEmpty()) |
108 | 0 | { |
109 | 0 | oSRS.exportToWkt(&pszWTKString); |
110 | 0 | } |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | 15 | GByte chType = 0; |
115 | 15 | if (VSIFReadL(&chType, 1, 1, fpVCT) != 1) |
116 | 0 | { |
117 | 0 | VSIFCloseL(fpVCT); |
118 | 0 | CSLDestroy(papszVDC); |
119 | 0 | CPLFree(pszWTKString); |
120 | 0 | return FALSE; |
121 | 0 | } |
122 | | |
123 | 15 | if (chType == 1) |
124 | 0 | eType = wkbPoint; |
125 | 15 | else if (chType == 2) |
126 | 0 | eType = wkbLineString; |
127 | 15 | else if (chType == 3) |
128 | 0 | eType = wkbPolygon; |
129 | 15 | else |
130 | 15 | { |
131 | 15 | CPLError(CE_Failure, CPLE_AppDefined, "Unsupported geometry type : %d", |
132 | 15 | static_cast<int>(chType)); |
133 | 15 | VSIFCloseL(fpVCT); |
134 | 15 | CSLDestroy(papszVDC); |
135 | 15 | CPLFree(pszWTKString); |
136 | 15 | return FALSE; |
137 | 15 | } |
138 | | |
139 | 0 | const char *pszMinX = CSLFetchNameValue(papszVDC, "min. X"); |
140 | 0 | const char *pszMaxX = CSLFetchNameValue(papszVDC, "max. X"); |
141 | 0 | const char *pszMinY = CSLFetchNameValue(papszVDC, "min. Y"); |
142 | 0 | const char *pszMaxY = CSLFetchNameValue(papszVDC, "max. Y"); |
143 | |
|
144 | 0 | OGRIdrisiLayer *poLayer = |
145 | 0 | new OGRIdrisiLayer(pszFilename, CPLGetBasenameSafe(pszFilename).c_str(), |
146 | 0 | fpVCT, eType, pszWTKString); |
147 | 0 | papoLayers = static_cast<OGRLayer **>(CPLMalloc(sizeof(OGRLayer *))); |
148 | 0 | papoLayers[nLayers++] = poLayer; |
149 | |
|
150 | 0 | if (pszMinX != nullptr && pszMaxX != nullptr && pszMinY != nullptr && |
151 | 0 | pszMaxY != nullptr) |
152 | 0 | { |
153 | 0 | poLayer->SetExtent(CPLAtof(pszMinX), CPLAtof(pszMinY), CPLAtof(pszMaxX), |
154 | 0 | CPLAtof(pszMaxY)); |
155 | 0 | } |
156 | |
|
157 | 0 | CPLFree(pszWTKString); |
158 | |
|
159 | 0 | CSLDestroy(papszVDC); |
160 | |
|
161 | 0 | return TRUE; |
162 | 15 | } |