1 : /******************************************************************************
2 : * $Id: ogravce00layer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: OGR
5 : * Purpose: Implements OGRAVCE00Layer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : * James Flemer <jflemer@alum.rpi.edu>
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
11 : * Copyright (c) 2006, James Flemer <jflemer@alum.rpi.edu>
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "ogr_avc.h"
33 : #include "ogr_api.h"
34 : #include "cpl_conv.h"
35 : #include "cpl_string.h"
36 :
37 : CPL_CVSID("$Id: ogravce00layer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
38 :
39 : /************************************************************************/
40 : /* OGRAVCE00Layer() */
41 : /************************************************************************/
42 :
43 2 : OGRAVCE00Layer::OGRAVCE00Layer( OGRAVCDataSource *poDSIn,
44 : AVCE00Section *psSectionIn )
45 : : OGRAVCLayer( psSectionIn->eType, poDSIn ),
46 : psSection(psSectionIn),
47 : psRead(NULL),
48 : poArcLayer(NULL),
49 : nFeatureCount(-1),
50 : bNeedReset(0),
51 : nNextFID(1),
52 : psTableSection(NULL),
53 : psTableRead(NULL),
54 : pszTableFilename(NULL),
55 : nTablePos(0),
56 : nTableBaseField(0),
57 2 : nTableAttrIndex(-1)
58 : {
59 2 : SetupFeatureDefinition( psSection->pszName );
60 : /* psRead = AVCE00ReadOpenE00(psSection->pszFilename); */
61 :
62 : #if 0
63 : szTableName[0] = '\0';
64 : if( psSection->eType == AVCFilePAL )
65 : sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
66 : else if( psSection->eType == AVCFileRPL )
67 : sprintf( szTableName, "%s.PAT%s", poDS->GetCoverageName(),
68 : psSectionIn->pszName );
69 : else if( psSection->eType == AVCFileARC )
70 : sprintf( szTableName, "%s.AAT", poDS->GetCoverageName() );
71 : else if( psSection->eType == AVCFileLAB )
72 : {
73 : AVCE00ReadPtr psInfo = ((OGRAVCE00DataSource *) poDS)->GetInfo();
74 :
75 : sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
76 :
77 : for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
78 : {
79 : if( psInfo->pasSections[iSection].eType == AVCFilePAL )
80 : nTableAttrIndex = poFeatureDefn->GetFieldIndex( "PolyId" );
81 : }
82 : }
83 :
84 : #endif
85 2 : }
86 :
87 : /************************************************************************/
88 : /* ~OGRAVCE00Layer() */
89 : /************************************************************************/
90 :
91 4 : OGRAVCE00Layer::~OGRAVCE00Layer()
92 :
93 : {
94 2 : if (psRead)
95 : {
96 1 : AVCE00ReadCloseE00(psRead);
97 1 : psRead = NULL;
98 : }
99 :
100 2 : if (psTableRead)
101 : {
102 0 : AVCE00ReadCloseE00(psTableRead);
103 0 : psTableRead = NULL;
104 : }
105 :
106 2 : if (pszTableFilename)
107 : {
108 0 : CPLFree(pszTableFilename);
109 0 : pszTableFilename = NULL;
110 : }
111 4 : }
112 :
113 : /************************************************************************/
114 : /* ResetReading() */
115 : /************************************************************************/
116 :
117 2 : void OGRAVCE00Layer::ResetReading()
118 :
119 : {
120 2 : if (psRead)
121 : {
122 2 : AVCE00ReadGotoSectionE00(psRead, psSection, 0);
123 : }
124 :
125 2 : if (psTableRead)
126 : {
127 0 : AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0);
128 : }
129 :
130 2 : bNeedReset = FALSE;
131 2 : nNextFID = 1;
132 2 : }
133 :
134 : /************************************************************************/
135 : /* GetFeature() */
136 : /************************************************************************/
137 :
138 9 : OGRFeature *OGRAVCE00Layer::GetFeature( long nFID )
139 :
140 : {
141 : /* -------------------------------------------------------------------- */
142 : /* If we haven't started yet, open the file now. */
143 : /* -------------------------------------------------------------------- */
144 9 : if( psRead == NULL )
145 : {
146 1 : psRead = AVCE00ReadOpenE00(psSection->pszFilename);
147 1 : if (psRead == NULL)
148 0 : return NULL;
149 : /* advance to the specified line number */
150 1 : if (AVCE00ReadGotoSectionE00(psRead, psSection, 0) != 0)
151 0 : return NULL;
152 1 : nNextFID = 1;
153 : }
154 :
155 : /* -------------------------------------------------------------------- */
156 : /* Read the raw feature - the -3 fid is a special flag */
157 : /* indicating serial access. */
158 : /* -------------------------------------------------------------------- */
159 : void *pFeature;
160 :
161 9 : if( nFID == -3 )
162 : {
163 18 : while( (pFeature = AVCE00ReadNextObjectE00(psRead)) != NULL
164 : && psRead->hParseInfo->eFileType != AVCFileUnknown
165 : && !MatchesSpatialFilter( pFeature ) )
166 : {
167 0 : nNextFID++;
168 : }
169 : }
170 : else
171 : {
172 0 : bNeedReset = TRUE;
173 :
174 0 : if (nNextFID > nFID)
175 : {
176 : /* advance to the specified line number */
177 0 : if (AVCE00ReadGotoSectionE00(psRead, psSection, 0) != 0)
178 0 : return NULL;
179 : }
180 :
181 0 : do
182 : {
183 0 : pFeature = AVCE00ReadNextObjectE00(psRead);
184 0 : ++nNextFID;
185 : }
186 : while (NULL != pFeature && nNextFID <= nFID);
187 : }
188 :
189 9 : if( pFeature == NULL )
190 1 : return NULL;
191 :
192 : /* -------------------------------------------------------------------- */
193 : /* Translate the feature. */
194 : /* -------------------------------------------------------------------- */
195 : OGRFeature *poFeature;
196 :
197 8 : poFeature = TranslateFeature( pFeature );
198 8 : if( poFeature == NULL )
199 0 : return NULL;
200 :
201 : /* -------------------------------------------------------------------- */
202 : /* LAB's we have to assign the FID to directly, since it */
203 : /* doesn't seem to be stored in the file structure. */
204 : /* -------------------------------------------------------------------- */
205 8 : if( psSection->eType == AVCFileLAB )
206 : {
207 0 : if( nFID == -3 )
208 0 : poFeature->SetFID( nNextFID++ );
209 : else
210 0 : poFeature->SetFID( nFID );
211 : }
212 :
213 : /* -------------------------------------------------------------------- */
214 : /* If this is a polygon layer, try to assemble the arcs to form */
215 : /* the whole polygon geometry. */
216 : /* -------------------------------------------------------------------- */
217 8 : if( psSection->eType == AVCFilePAL
218 : || psSection->eType == AVCFileRPL )
219 : {
220 0 : FormPolygonGeometry( poFeature, (AVCPal *) pFeature );
221 : }
222 :
223 : /* -------------------------------------------------------------------- */
224 : /* If we have an attribute table, append the attributes now. */
225 : /* -------------------------------------------------------------------- */
226 8 : AppendTableFields( poFeature );
227 :
228 8 : return poFeature;
229 : }
230 :
231 : /************************************************************************/
232 : /* GetNextFeature() */
233 : /************************************************************************/
234 :
235 9 : OGRFeature *OGRAVCE00Layer::GetNextFeature()
236 :
237 : {
238 9 : if( bNeedReset )
239 0 : ResetReading();
240 :
241 9 : OGRFeature *poFeature = GetFeature( -3 );
242 :
243 : // Skip universe polygon.
244 9 : if( poFeature != NULL && poFeature->GetFID() == 1
245 : && psSection->eType == AVCFilePAL )
246 : {
247 0 : OGRFeature::DestroyFeature( poFeature );
248 0 : poFeature = GetFeature( -3 );
249 : }
250 :
251 18 : while( poFeature != NULL
252 : && ((m_poAttrQuery != NULL
253 : && !m_poAttrQuery->Evaluate( poFeature ) )
254 : || !FilterGeometry( poFeature->GetGeometryRef() ) ) )
255 : {
256 0 : OGRFeature::DestroyFeature( poFeature );
257 0 : poFeature = GetFeature( -3 );
258 : }
259 :
260 9 : if( poFeature == NULL )
261 1 : ResetReading();
262 :
263 9 : return poFeature;
264 : }
265 :
266 : /************************************************************************/
267 : /* TestCapability() */
268 : /************************************************************************/
269 :
270 : #if 0
271 : int OGRAVCE00Layer::TestCapability( const char * pszCap )
272 :
273 : {
274 : if( eSectionType == AVCFileARC && EQUAL(pszCap,OLCRandomRead) )
275 : return TRUE;
276 : else
277 : return OGRAVCLayer::TestCapability( pszCap );
278 : }
279 : #endif
280 :
281 : /************************************************************************/
282 : /* FormPolygonGeometry() */
283 : /* */
284 : /* Collect all the arcs forming edges to this polygon and form */
285 : /* them into the appropriate OGR geometry on the target feature. */
286 : /************************************************************************/
287 :
288 0 : int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
289 : AVCPal *psPAL )
290 : {
291 : /* -------------------------------------------------------------------- */
292 : /* Try to find the corresponding ARC layer if not already */
293 : /* recorded. */
294 : /* -------------------------------------------------------------------- */
295 0 : if( poArcLayer == NULL )
296 : {
297 : int i;
298 :
299 0 : for( i = 0; i < poDS->GetLayerCount(); i++ )
300 : {
301 0 : OGRAVCE00Layer *poLayer = (OGRAVCE00Layer *) poDS->GetLayer(i);
302 :
303 0 : if( poLayer->eSectionType == AVCFileARC )
304 0 : poArcLayer = poLayer;
305 : }
306 :
307 0 : if( poArcLayer == NULL )
308 0 : return FALSE;
309 : }
310 :
311 : /* -------------------------------------------------------------------- */
312 : /* Read all the arcs related to this polygon, making a working */
313 : /* copy of them since the one returned by AVC is temporary. */
314 : /* -------------------------------------------------------------------- */
315 0 : OGRGeometryCollection oArcs;
316 : int iArc;
317 :
318 0 : for( iArc = 0; iArc < psPAL->numArcs; iArc++ )
319 : {
320 : OGRFeature *poArc;
321 :
322 0 : if( psPAL->pasArcs[iArc].nArcId == 0 )
323 0 : continue;
324 :
325 : // If the other side of the line is the same polygon then this
326 : // arc is a "bridge" arc and can be discarded. If we don't discard
327 : // it, then we should double it as bridge arcs seem to only appear
328 : // once. But by discarding it we ensure a multi-ring polygon will be
329 : // properly formed.
330 0 : if( psPAL->pasArcs[iArc].nAdjPoly == psPAL->nPolyId )
331 0 : continue;
332 :
333 0 : poArc = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
334 :
335 0 : if( poArc == NULL )
336 0 : return FALSE;
337 :
338 0 : if( poArc->GetGeometryRef() == NULL )
339 0 : return FALSE;
340 :
341 0 : oArcs.addGeometry( poArc->GetGeometryRef() );
342 0 : OGRFeature::DestroyFeature( poArc );
343 : }
344 :
345 : OGRErr eErr;
346 : OGRPolygon *poPolygon;
347 :
348 : poPolygon = (OGRPolygon *)
349 : OGRBuildPolygonFromEdges( (OGRGeometryH) &oArcs, TRUE, FALSE,
350 0 : 0.0, &eErr );
351 0 : if( poPolygon != NULL )
352 0 : poFeature->SetGeometryDirectly( poPolygon );
353 :
354 0 : return eErr == OGRERR_NONE;
355 : }
356 :
357 : /************************************************************************/
358 : /* CheckSetupTable() */
359 : /* */
360 : /* Check if the named table exists, and if so, setup access to */
361 : /* it (open it), and add it's fields to the feature class */
362 : /* definition. */
363 : /************************************************************************/
364 :
365 8 : int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
366 : {
367 8 : if (psTableRead)
368 0 : return FALSE;
369 :
370 8 : const char *pszTableType = NULL;
371 8 : switch (eSectionType)
372 : {
373 : case AVCFileARC:
374 4 : pszTableType = ".AAT";
375 4 : break;
376 :
377 : case AVCFilePAL:
378 : case AVCFileLAB:
379 4 : pszTableType = ".PAT";
380 : break;
381 :
382 : default:
383 : break;
384 : }
385 :
386 : /* -------------------------------------------------------------------- */
387 : /* Is the table type found anywhere in the section pszName? Do */
388 : /* a case insensitive check. */
389 : /* -------------------------------------------------------------------- */
390 8 : if( pszTableType == NULL )
391 0 : return FALSE;
392 :
393 : int iCheckOff;
394 528 : for( iCheckOff = 0;
395 264 : psTblSectionIn->pszName[iCheckOff] != '\0';
396 : iCheckOff++ )
397 : {
398 256 : if( EQUALN(psTblSectionIn->pszName + iCheckOff,
399 : pszTableType, strlen(pszTableType) ) )
400 0 : break;
401 : }
402 :
403 8 : if( psTblSectionIn->pszName[iCheckOff] == '\0' )
404 8 : return FALSE;
405 :
406 0 : psTableSection = psTblSectionIn;
407 :
408 : /* -------------------------------------------------------------------- */
409 : /* Try opening the table. */
410 : /* -------------------------------------------------------------------- */
411 0 : psTableRead = AVCE00ReadOpenE00(psTblSectionIn->pszFilename);
412 0 : if (psTableRead == NULL)
413 0 : return FALSE;
414 :
415 : /* advance to the specified line number */
416 0 : if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
417 : {
418 0 : AVCE00ReadCloseE00(psTableRead);
419 0 : psTableRead = NULL;
420 0 : return FALSE;
421 : }
422 :
423 0 : AVCE00ReadNextObjectE00(psTableRead);
424 0 : bNeedReset = 1;
425 :
426 0 : pszTableFilename = CPLStrdup(psTblSectionIn->pszFilename);
427 0 : nTableBaseField = poFeatureDefn->GetFieldCount();
428 :
429 0 : if (eSectionType == AVCFileLAB)
430 : {
431 0 : AVCE00ReadE00Ptr psInfo = ((OGRAVCE00DataSource *) poDS)->GetInfo();
432 0 : for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
433 : {
434 0 : if( psInfo->pasSections[iSection].eType == AVCFilePAL )
435 0 : nTableAttrIndex = poFeatureDefn->GetFieldIndex( "PolyId" );
436 : }
437 : }
438 :
439 : /* -------------------------------------------------------------------- */
440 : /* Setup attributes. */
441 : /* -------------------------------------------------------------------- */
442 0 : AppendTableDefinition( psTableRead->hParseInfo->hdr.psTableDef );
443 :
444 : /* -------------------------------------------------------------------- */
445 : /* Close table so we don't have to many files open at once. */
446 : /* -------------------------------------------------------------------- */
447 : /* AVCE00ReadCloseE00( psTableRead ); */
448 :
449 0 : return TRUE;
450 : }
451 :
452 : /************************************************************************/
453 : /* AppendTableFields() */
454 : /************************************************************************/
455 :
456 8 : int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
457 :
458 : {
459 8 : if (psTableRead == NULL)
460 8 : return FALSE;
461 :
462 : /* -------------------------------------------------------------------- */
463 : /* Open the table if it is currently closed. */
464 : /* -------------------------------------------------------------------- */
465 0 : if (psTableRead == NULL)
466 : {
467 0 : psTableRead = AVCE00ReadOpenE00(pszTableFilename);
468 0 : if (psTableRead == NULL)
469 0 : return FALSE;
470 :
471 : /* advance to the specified line number */
472 0 : if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
473 : {
474 0 : AVCE00ReadCloseE00(psTableRead);
475 0 : psTableRead = NULL;
476 0 : return FALSE;
477 : }
478 0 : nTablePos = 0;
479 : }
480 :
481 : /* -------------------------------------------------------------------- */
482 : /* Read the info record. */
483 : /* */
484 : /* We usually assume the FID of the feature is the key but in a */
485 : /* polygon coverage we need to use the PolyId attribute of LAB */
486 : /* features to lookup the related attributes. In this case */
487 : /* nTableAttrIndex will already be setup to refer to the */
488 : /* PolyId field. */
489 : /* -------------------------------------------------------------------- */
490 : int nRecordId;
491 : void *hRecord;
492 :
493 0 : if( nTableAttrIndex == -1 )
494 0 : nRecordId = poFeature->GetFID();
495 : else
496 0 : nRecordId = poFeature->GetFieldAsInteger( nTableAttrIndex );
497 :
498 0 : if (nRecordId <= nTablePos)
499 : {
500 0 : if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
501 0 : return FALSE;
502 0 : nTablePos = 0;
503 : }
504 :
505 0 : do
506 : {
507 0 : hRecord = AVCE00ReadNextObjectE00(psTableRead);
508 0 : ++nTablePos;
509 : }
510 : while (NULL != hRecord && nTablePos < nRecordId);
511 :
512 0 : if( hRecord == NULL )
513 0 : return FALSE;
514 :
515 :
516 : /* -------------------------------------------------------------------- */
517 : /* Translate it. */
518 : /* -------------------------------------------------------------------- */
519 : return TranslateTableFields( poFeature, nTableBaseField,
520 : psTableRead->hParseInfo->hdr.psTableDef,
521 0 : (AVCField *) hRecord );
522 : }
523 :
524 :
525 0 : int OGRAVCE00Layer::GetFeatureCount(int bForce)
526 : {
527 0 : if (bForce && nFeatureCount < 0)
528 : {
529 0 : if (psSection->nFeatureCount < 0)
530 : {
531 0 : nFeatureCount = OGRLayer::GetFeatureCount(bForce);
532 : }
533 : else
534 : {
535 0 : nFeatureCount = psSection->nFeatureCount;
536 0 : if (psSection->eType == AVCFilePAL)
537 0 : --nFeatureCount;
538 : }
539 : }
540 0 : return nFeatureCount;
541 : }
|