Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: Interlis 1 Translator 4 : * Purpose: Implements OGRILI1DataSource class. 5 : * Author: Pirmin Kalberer, Sourcepole AG 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG 9 : * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "cpl_conv.h" 15 : #include "cpl_string.h" 16 : 17 : #include "ili1reader.h" 18 : #include "ogr_ili1.h" 19 : 20 : #include <string> 21 : 22 : /************************************************************************/ 23 : /* OGRILI1DataSource() */ 24 : /************************************************************************/ 25 : 26 67 : OGRILI1DataSource::OGRILI1DataSource() 27 67 : : poImdReader(new ImdReader(1)), poReader(nullptr), nLayers(0), 28 67 : papoLayers(nullptr) 29 : { 30 67 : } 31 : 32 : /************************************************************************/ 33 : /* ~OGRILI1DataSource() */ 34 : /************************************************************************/ 35 : 36 134 : OGRILI1DataSource::~OGRILI1DataSource() 37 : 38 : { 39 67 : for (int i = 0; i < nLayers; i++) 40 : { 41 0 : delete papoLayers[i]; 42 : } 43 67 : CPLFree(papoLayers); 44 : 45 67 : DestroyILI1Reader(poReader); 46 67 : delete poImdReader; 47 134 : } 48 : 49 : /************************************************************************/ 50 : /* Open() */ 51 : /************************************************************************/ 52 : 53 67 : int OGRILI1DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn, 54 : int bTestOpen) 55 : 56 : { 57 67 : if (strlen(pszNewName) == 0) 58 : { 59 0 : return FALSE; 60 : } 61 : 62 134 : std::string osBasename; 63 134 : std::string osModelFilename; 64 67 : if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr) 65 : { 66 0 : osBasename = pszNewName; 67 0 : osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL"); 68 : } 69 : else 70 : { 71 67 : char **filenames = CSLTokenizeString2(pszNewName, ",", 0); 72 67 : int nCount = CSLCount(filenames); 73 67 : if (nCount == 0) 74 : { 75 0 : CSLDestroy(filenames); 76 0 : return FALSE; 77 : } 78 67 : osBasename = filenames[0]; 79 : 80 67 : if (nCount > 1) 81 64 : osModelFilename = filenames[1]; 82 : 83 67 : CSLDestroy(filenames); 84 : } 85 : 86 : /* -------------------------------------------------------------------- */ 87 : /* Open the source file. */ 88 : /* -------------------------------------------------------------------- */ 89 67 : VSILFILE *fp = VSIFOpenL(osBasename.c_str(), "r"); 90 67 : if (fp == nullptr) 91 : { 92 52 : if (!bTestOpen) 93 0 : CPLError(CE_Failure, CPLE_OpenFailed, 94 : "Failed to open ILI1 file `%s'.", pszNewName); 95 : 96 52 : return FALSE; 97 : } 98 : 99 : /* -------------------------------------------------------------------- */ 100 : /* If we aren't sure it is ILI1, load a header chunk and check */ 101 : /* for signs it is ILI1 */ 102 : /* -------------------------------------------------------------------- */ 103 : char szHeader[1000]; 104 : 105 15 : if (bTestOpen) 106 : { 107 15 : int nLen = (int)VSIFReadL(szHeader, 1, sizeof(szHeader), fp); 108 15 : if (nLen == sizeof(szHeader)) 109 4 : szHeader[sizeof(szHeader) - 1] = '\0'; 110 : else 111 11 : szHeader[nLen] = '\0'; 112 : 113 15 : if (strstr(szHeader, "SCNT") == nullptr) 114 : { 115 2 : VSIFCloseL(fp); 116 2 : return FALSE; 117 : } 118 : } 119 : 120 : /* -------------------------------------------------------------------- */ 121 : /* We assume now that it is ILI1. Close and instantiate a */ 122 : /* ILI1Reader on it. */ 123 : /* -------------------------------------------------------------------- */ 124 13 : VSIFCloseL(fp); 125 : 126 13 : poReader = CreateILI1Reader(); 127 13 : if (poReader == nullptr) 128 : { 129 0 : CPLError(CE_Failure, CPLE_AppDefined, 130 : "File %s appears to be ILI1 but the ILI1 reader cannot\n" 131 : "be instantiated, likely because Xerces support was not\n" 132 : "configured in.", 133 : pszNewName); 134 0 : return FALSE; 135 : } 136 : 137 13 : poReader->OpenFile(osBasename.c_str()); 138 : 139 13 : if (osModelFilename.length() > 0) 140 13 : poReader->ReadModel(poImdReader, osModelFilename.c_str(), this); 141 : 142 : CPLConfigOptionSetter oSetter("OGR_ARC_STEPSIZE", "0.96", 143 13 : /* bSetOnlyIfUndefined = */ true); 144 : 145 : // Parse model and read data - without surface join and area polygonizing. 146 13 : poReader->ReadFeatures(); 147 : 148 13 : return TRUE; 149 : } 150 : 151 : /************************************************************************/ 152 : /* TestCapability() */ 153 : /************************************************************************/ 154 : 155 0 : int OGRILI1DataSource::TestCapability(const char *pszCap) 156 : 157 : { 158 0 : if (EQUAL(pszCap, ODsCCurveGeometries)) 159 0 : return TRUE; 160 0 : else if (EQUAL(pszCap, ODsCZGeometries)) 161 0 : return TRUE; 162 : 163 0 : return FALSE; 164 : } 165 : 166 : /************************************************************************/ 167 : /* GetLayer() */ 168 : /************************************************************************/ 169 : 170 23 : OGRLayer *OGRILI1DataSource::GetLayer(int iLayer) 171 : { 172 23 : if (!poReader) 173 : { 174 0 : if (iLayer < 0 || iLayer >= nLayers) 175 0 : return nullptr; 176 0 : return papoLayers[iLayer]; 177 : } 178 23 : return poReader->GetLayer(iLayer); 179 : } 180 : 181 : /************************************************************************/ 182 : /* GetLayerByName() */ 183 : /************************************************************************/ 184 : 185 26 : OGRILI1Layer *OGRILI1DataSource::GetLayerByName(const char *pszLayerName) 186 : { 187 26 : if (!poReader) 188 : { 189 0 : return cpl::down_cast<OGRILI1Layer *>( 190 0 : GDALDataset::GetLayerByName(pszLayerName)); 191 : } 192 : 193 26 : return cpl::down_cast<OGRILI1Layer *>( 194 52 : poReader->GetLayerByName(pszLayerName)); 195 : }