1 : /******************************************************************************
2 : * $Id: ogridrisilayer.cpp 23388 2011-11-18 23:34:35Z rouault $
3 : *
4 : * Project: Idrisi Translator
5 : * Purpose: Implements OGRIdrisiLayer class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_idrisi.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "ogr_p.h"
34 : #include "ogr_srs_api.h"
35 :
36 : CPL_CVSID("$Id: ogridrisilayer.cpp 23388 2011-11-18 23:34:35Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRIdrisiLayer() */
40 : /************************************************************************/
41 :
42 3 : OGRIdrisiLayer::OGRIdrisiLayer( const char* pszLayerName, VSILFILE* fp,
43 : OGRwkbGeometryType eGeomType,
44 3 : const char* pszWTKString )
45 :
46 : {
47 3 : this->fp = fp;
48 3 : this->eGeomType = eGeomType;
49 3 : nNextFID = 1;
50 3 : bEOF = FALSE;
51 :
52 3 : if (pszWTKString)
53 : {
54 3 : poSRS = new OGRSpatialReference();
55 3 : char* pszTmp = (char*)pszWTKString;
56 3 : poSRS->importFromWkt(&pszTmp);
57 : }
58 : else
59 0 : poSRS = NULL;
60 :
61 3 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
62 3 : poFeatureDefn->Reference();
63 3 : poFeatureDefn->SetGeomType( eGeomType );
64 :
65 3 : OGRFieldDefn oFieldDefn("id", OFTReal);
66 3 : poFeatureDefn->AddFieldDefn( &oFieldDefn );
67 :
68 3 : bExtentValid = FALSE;
69 3 : dfMinX = dfMinY = dfMaxX = dfMaxY = 0.0;
70 :
71 3 : VSIFSeekL( fp, 1, SEEK_SET );
72 3 : if (VSIFReadL( &nTotalFeatures, sizeof(unsigned int), 1, fp ) != 1)
73 0 : nTotalFeatures = 0;
74 : CPL_LSBPTR32(&nTotalFeatures);
75 :
76 3 : ResetReading();
77 3 : }
78 :
79 : /************************************************************************/
80 : /* ~OGRIdrisiLayer() */
81 : /************************************************************************/
82 :
83 3 : OGRIdrisiLayer::~OGRIdrisiLayer()
84 :
85 : {
86 3 : if( poSRS != NULL )
87 3 : poSRS->Release();
88 :
89 3 : poFeatureDefn->Release();
90 :
91 3 : VSIFCloseL( fp );
92 3 : }
93 :
94 : /************************************************************************/
95 : /* ResetReading() */
96 : /************************************************************************/
97 :
98 11 : void OGRIdrisiLayer::ResetReading()
99 :
100 : {
101 11 : nNextFID = 1;
102 11 : bEOF = FALSE;
103 11 : VSIFSeekL( fp, 0x105, SEEK_SET );
104 11 : }
105 :
106 : /************************************************************************/
107 : /* GetNextFeature() */
108 : /************************************************************************/
109 :
110 9 : OGRFeature *OGRIdrisiLayer::GetNextFeature()
111 : {
112 : OGRFeature *poFeature;
113 :
114 0 : while(TRUE)
115 : {
116 9 : if (bEOF)
117 0 : return NULL;
118 :
119 9 : poFeature = GetNextRawFeature();
120 9 : if (poFeature == NULL)
121 : {
122 3 : bEOF = TRUE;
123 3 : return NULL;
124 : }
125 :
126 6 : if((m_poFilterGeom == NULL
127 : || FilterGeometry( poFeature->GetGeometryRef() ) )
128 : && (m_poAttrQuery == NULL
129 : || m_poAttrQuery->Evaluate( poFeature )) )
130 : {
131 6 : return poFeature;
132 : }
133 : else
134 0 : delete poFeature;
135 : }
136 : }
137 :
138 : /************************************************************************/
139 : /* TestCapability() */
140 : /************************************************************************/
141 :
142 6 : int OGRIdrisiLayer::TestCapability( const char * pszCap )
143 :
144 : {
145 6 : if (EQUAL(pszCap, OLCFastFeatureCount))
146 3 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
147 :
148 3 : if (EQUAL(pszCap, OLCFastGetExtent))
149 3 : return bExtentValid;
150 :
151 0 : return FALSE;
152 : }
153 :
154 : /************************************************************************/
155 : /* GetNextRawFeature() */
156 : /************************************************************************/
157 :
158 15 : OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
159 : {
160 6 : while(TRUE)
161 : {
162 15 : if (eGeomType == wkbPoint)
163 : {
164 : double dfId;
165 : double dfX, dfY;
166 7 : if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
167 : VSIFReadL(&dfX, sizeof(double), 1, fp) != 1 ||
168 : VSIFReadL(&dfY, sizeof(double), 1, fp) != 1)
169 : {
170 1 : return NULL;
171 : }
172 : CPL_LSBPTR64(&dfId);
173 : CPL_LSBPTR64(&dfX);
174 : CPL_LSBPTR64(&dfY);
175 :
176 6 : if (m_poFilterGeom != NULL &&
177 : (dfX < m_sFilterEnvelope.MinX ||
178 : dfX > m_sFilterEnvelope.MaxX ||
179 : dfY < m_sFilterEnvelope.MinY ||
180 : dfY > m_sFilterEnvelope.MaxY))
181 : {
182 3 : nNextFID ++;
183 3 : continue;
184 : }
185 :
186 3 : OGRPoint* poGeom = new OGRPoint(dfX, dfY);
187 3 : if (poSRS)
188 3 : poGeom->assignSpatialReference(poSRS);
189 3 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
190 3 : poFeature->SetField(0, dfId);
191 3 : poFeature->SetFID(nNextFID ++);
192 3 : poFeature->SetGeometryDirectly(poGeom);
193 3 : return poFeature;
194 : }
195 8 : else if (eGeomType == wkbLineString)
196 : {
197 : double dfId;
198 : double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape;
199 : unsigned int nNodes;
200 :
201 5 : if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
202 : VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
203 : VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
204 : VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
205 : VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
206 : {
207 1 : return NULL;
208 : }
209 : CPL_LSBPTR64(&dfId);
210 : CPL_LSBPTR64(&dfMinXShape);
211 : CPL_LSBPTR64(&dfMaxXShape);
212 : CPL_LSBPTR64(&dfMinYShape);
213 : CPL_LSBPTR64(&dfMaxYShape);
214 :
215 4 : if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
216 : {
217 0 : return NULL;
218 : }
219 : CPL_LSBPTR32(&nNodes);
220 :
221 4 : if (nNodes > 100 * 1000 * 1000)
222 0 : return NULL;
223 :
224 4 : if (m_poFilterGeom != NULL &&
225 : (dfMaxXShape < m_sFilterEnvelope.MinX ||
226 : dfMinXShape > m_sFilterEnvelope.MaxX ||
227 : dfMaxYShape < m_sFilterEnvelope.MinY ||
228 : dfMinYShape > m_sFilterEnvelope.MaxY))
229 : {
230 2 : nNextFID ++;
231 2 : VSIFSeekL(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR);
232 2 : continue;
233 : }
234 :
235 2 : OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nNodes);
236 2 : if (poRawPoints == NULL)
237 : {
238 0 : return NULL;
239 : }
240 :
241 2 : if ((unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes)
242 : {
243 0 : VSIFree(poRawPoints);
244 0 : return NULL;
245 : }
246 :
247 : #if defined(CPL_MSB)
248 : for(unsigned int iNode=0; iNode<nNodes; iNode++)
249 : {
250 : CPL_LSBPTR64(&poRawPoints[iNode].x);
251 : CPL_LSBPTR64(&poRawPoints[iNode].y);
252 : }
253 : #endif
254 :
255 2 : OGRLineString* poGeom = new OGRLineString();
256 2 : poGeom->setPoints(nNodes, poRawPoints, NULL);
257 :
258 2 : VSIFree(poRawPoints);
259 :
260 2 : if (poSRS)
261 2 : poGeom->assignSpatialReference(poSRS);
262 2 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
263 2 : poFeature->SetField(0, dfId);
264 2 : poFeature->SetFID(nNextFID ++);
265 2 : poFeature->SetGeometryDirectly(poGeom);
266 2 : return poFeature;
267 : }
268 : else /* if (eGeomType == wkbPolygon) */
269 : {
270 : double dfId;
271 : double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape;
272 : unsigned int nParts;
273 : unsigned int nTotalNodes;
274 :
275 3 : if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
276 : VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
277 : VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
278 : VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
279 : VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
280 : {
281 1 : return NULL;
282 : }
283 : CPL_LSBPTR64(&dfId);
284 : CPL_LSBPTR64(&dfMinXShape);
285 : CPL_LSBPTR64(&dfMaxXShape);
286 : CPL_LSBPTR64(&dfMinYShape);
287 : CPL_LSBPTR64(&dfMaxYShape);
288 2 : if (VSIFReadL(&nParts, sizeof(unsigned int), 1, fp) != 1 ||
289 : VSIFReadL(&nTotalNodes, sizeof(unsigned int), 1, fp) != 1)
290 : {
291 0 : return NULL;
292 : }
293 : CPL_LSBPTR32(&nParts);
294 : CPL_LSBPTR32(&nTotalNodes);
295 :
296 2 : if (nParts > 100000 || nTotalNodes > 100 * 1000 * 1000)
297 0 : return NULL;
298 :
299 2 : if (m_poFilterGeom != NULL &&
300 : (dfMaxXShape < m_sFilterEnvelope.MinX ||
301 : dfMinXShape > m_sFilterEnvelope.MaxX ||
302 : dfMaxYShape < m_sFilterEnvelope.MinY ||
303 : dfMinYShape > m_sFilterEnvelope.MaxY))
304 : {
305 : unsigned int iPart;
306 3 : for(iPart = 0; iPart < nParts; iPart ++)
307 : {
308 : unsigned int nNodes;
309 2 : if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
310 0 : return NULL;
311 : CPL_LSBPTR32(&nNodes);
312 2 : if (nNodes > nTotalNodes)
313 0 : return NULL;
314 2 : VSIFSeekL(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR);
315 : }
316 1 : nNextFID ++;
317 1 : continue;
318 : }
319 :
320 1 : OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nTotalNodes);
321 1 : if (poRawPoints == NULL)
322 : {
323 0 : return NULL;
324 : }
325 :
326 : unsigned int iPart;
327 1 : OGRPolygon* poGeom = new OGRPolygon();
328 6 : for(iPart = 0; iPart < nParts; iPart ++)
329 : {
330 : unsigned int nNodes;
331 2 : if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
332 : {
333 0 : VSIFree(poRawPoints);
334 0 : delete poGeom;
335 0 : return NULL;
336 : }
337 : CPL_LSBPTR32(&nNodes);
338 :
339 2 : if (nNodes > nTotalNodes ||
340 : (unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes)
341 : {
342 0 : VSIFree(poRawPoints);
343 0 : delete poGeom;
344 0 : return NULL;
345 : }
346 :
347 : #if defined(CPL_MSB)
348 : for(unsigned int iNode=0; iNode<nNodes; iNode++)
349 : {
350 : CPL_LSBPTR64(&poRawPoints[iNode].x);
351 : CPL_LSBPTR64(&poRawPoints[iNode].y);
352 : }
353 : #endif
354 :
355 2 : OGRLinearRing* poLR = new OGRLinearRing();
356 2 : poGeom->addRingDirectly(poLR);
357 2 : poLR->setPoints(nNodes, poRawPoints, NULL);
358 : }
359 :
360 1 : VSIFree(poRawPoints);
361 :
362 1 : if (poSRS)
363 1 : poGeom->assignSpatialReference(poSRS);
364 1 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
365 1 : poFeature->SetField(0, dfId);
366 1 : poFeature->SetFID(nNextFID ++);
367 1 : poFeature->SetGeometryDirectly(poGeom);
368 1 : return poFeature;
369 : }
370 : }
371 : }
372 :
373 : /************************************************************************/
374 : /* SetExtent() */
375 : /************************************************************************/
376 :
377 3 : void OGRIdrisiLayer::SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
378 : {
379 3 : bExtentValid = TRUE;
380 3 : this->dfMinX = dfMinX;
381 3 : this->dfMinY = dfMinY;
382 3 : this->dfMaxX = dfMaxX;
383 3 : this->dfMaxY = dfMaxY;
384 3 : }
385 :
386 : /************************************************************************/
387 : /* GetExtent() */
388 : /************************************************************************/
389 :
390 3 : OGRErr OGRIdrisiLayer::GetExtent(OGREnvelope *psExtent, int bForce)
391 : {
392 3 : if (!bExtentValid)
393 0 : return OGRLayer::GetExtent(psExtent, bForce);
394 :
395 3 : psExtent->MinX = dfMinX;
396 3 : psExtent->MinY = dfMinY;
397 3 : psExtent->MaxX = dfMaxX;
398 3 : psExtent->MaxY = dfMaxY;
399 3 : return OGRERR_NONE;
400 : }
401 :
402 : /************************************************************************/
403 : /* GetFeatureCount() */
404 : /************************************************************************/
405 :
406 3 : int OGRIdrisiLayer::GetFeatureCount( int bForce )
407 : {
408 3 : if (nTotalFeatures > 0 && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
409 3 : return nTotalFeatures;
410 :
411 0 : return OGRLayer::GetFeatureCount(bForce);
412 : }
|