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  * 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 #include "cpl_conv.h"
30 #include "cpl_string.h"
31 #include "idrisi.h"
32 #include "ogr_idrisi.h"
33 
34 CPL_CVSID("$Id: ogridrisidatasource.cpp ce778433e8ac725886855a39d2fe26f25aaf1fa4 2021-03-12 12:42:06 +0100 Even Rouault $")
35 
36 /************************************************************************/
37 /*                        OGRIdrisiDataSource()                         */
38 /************************************************************************/
39 
OGRIdrisiDataSource()40 OGRIdrisiDataSource::OGRIdrisiDataSource() :
41     pszName(nullptr),
42     papoLayers(nullptr),
43     nLayers(0)
44 {}
45 
46 /************************************************************************/
47 /*                       ~OGRIdrisiDataSource()                         */
48 /************************************************************************/
49 
~OGRIdrisiDataSource()50 OGRIdrisiDataSource::~OGRIdrisiDataSource()
51 
52 {
53     CPLFree( pszName );
54     for( int i = 0; i < nLayers; i++ )
55         delete papoLayers[i];
56     CPLFree( papoLayers );
57 }
58 
59 /************************************************************************/
60 /*                           TestCapability()                           */
61 /************************************************************************/
62 
TestCapability(const char *)63 int OGRIdrisiDataSource::TestCapability( const char * /* pszCap */ )
64 {
65     return FALSE;
66 }
67 
68 /************************************************************************/
69 /*                              GetLayer()                              */
70 /************************************************************************/
71 
GetLayer(int iLayer)72 OGRLayer *OGRIdrisiDataSource::GetLayer( int iLayer )
73 
74 {
75     if( iLayer < 0 || iLayer >= nLayers )
76         return nullptr;
77 
78     return papoLayers[iLayer];
79 }
80 
81 /************************************************************************/
82 /*                                Open()                                */
83 /************************************************************************/
84 
Open(const char * pszFilename)85 int OGRIdrisiDataSource::Open( const char * pszFilename )
86 
87 {
88     pszName = CPLStrdup( pszFilename );
89 
90     VSILFILE* fpVCT = VSIFOpenL(pszFilename, "rb");
91     if (fpVCT == nullptr)
92         return FALSE;
93 
94 // --------------------------------------------------------------------
95 //      Look for .vdc file
96 // --------------------------------------------------------------------
97     const char* pszVDCFilename = CPLResetExtension(pszFilename, "vdc");
98     VSILFILE* fpVDC = VSIFOpenL(pszVDCFilename, "rb");
99     if (fpVDC == nullptr)
100     {
101         pszVDCFilename = CPLResetExtension(pszFilename, "VDC");
102         fpVDC = VSIFOpenL(pszVDCFilename, "rb");
103     }
104 
105     char** papszVDC = nullptr;
106     if (fpVDC != nullptr)
107     {
108         VSIFCloseL(fpVDC);
109         fpVDC = nullptr;
110 
111         CPLPushErrorHandler(CPLQuietErrorHandler);
112         papszVDC = CSLLoad2(pszVDCFilename, 1024, 256, nullptr);
113         CPLPopErrorHandler();
114         CPLErrorReset();
115     }
116 
117     OGRwkbGeometryType eType = wkbUnknown;
118 
119     char* pszWTKString = nullptr;
120     if (papszVDC != nullptr)
121     {
122         CSLSetNameValueSeparator( papszVDC, ":" );
123 
124         const char *pszVersion = CSLFetchNameValue( papszVDC, "file format" );
125 
126         if( pszVersion == nullptr || !EQUAL( pszVersion, "IDRISI Vector A.1" ) )
127         {
128             CSLDestroy( papszVDC );
129             VSIFCloseL(fpVCT);
130             return FALSE;
131         }
132 
133         const char *pszRefSystem
134             = CSLFetchNameValue( papszVDC, "ref. system" );
135         const char *pszRefUnits = CSLFetchNameValue( papszVDC, "ref. units" );
136 
137         if (pszRefSystem != nullptr && pszRefUnits != nullptr)
138             IdrisiGeoReference2Wkt( pszFilename, pszRefSystem, pszRefUnits,
139                                     &pszWTKString);
140     }
141 
142     GByte chType = 0;
143     if (VSIFReadL(&chType, 1, 1, fpVCT) != 1)
144     {
145         VSIFCloseL(fpVCT);
146         CSLDestroy( papszVDC );
147         CPLFree(pszWTKString);
148         return FALSE;
149     }
150 
151     if (chType == 1)
152         eType = wkbPoint;
153     else if (chType == 2)
154         eType = wkbLineString;
155     else if (chType == 3)
156         eType = wkbPolygon;
157     else
158     {
159         CPLError( CE_Failure, CPLE_AppDefined, "Unsupported geometry type : %d",
160                   static_cast<int>(chType) );
161         VSIFCloseL(fpVCT);
162         CSLDestroy( papszVDC );
163         CPLFree(pszWTKString);
164         return FALSE;
165     }
166 
167     const char *pszMinX = CSLFetchNameValue( papszVDC, "min. X" );
168     const char *pszMaxX = CSLFetchNameValue( papszVDC, "max. X" );
169     const char *pszMinY = CSLFetchNameValue( papszVDC, "min. Y" );
170     const char *pszMaxY = CSLFetchNameValue( papszVDC, "max. Y" );
171 
172     OGRIdrisiLayer* poLayer = new OGRIdrisiLayer(pszFilename,
173                                                  CPLGetBasename(pszFilename),
174                                                  fpVCT, eType, pszWTKString);
175     papoLayers = static_cast<OGRLayer**>( CPLMalloc(sizeof(OGRLayer*)) );
176     papoLayers[nLayers ++] = poLayer;
177 
178     if( pszMinX != nullptr && pszMaxX != nullptr && pszMinY != nullptr &&
179         pszMaxY != nullptr)
180     {
181         poLayer->SetExtent(
182             CPLAtof(pszMinX), CPLAtof(pszMinY), CPLAtof(pszMaxX),
183             CPLAtof(pszMaxY) );
184     }
185 
186     CPLFree(pszWTKString);
187 
188     CSLDestroy( papszVDC );
189 
190     return TRUE;
191 }
192