1 : /******************************************************************************
2 : * $Id: ogravcbinlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: OGR
5 : * Purpose: Implements OGRAVCBinLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
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_avc.h"
31 : #include "ogr_api.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 :
35 : CPL_CVSID("$Id: ogravcbinlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
36 :
37 : /************************************************************************/
38 : /* OGRAVCBinLayer() */
39 : /************************************************************************/
40 :
41 2 : OGRAVCBinLayer::OGRAVCBinLayer( OGRAVCBinDataSource *poDSIn,
42 : AVCE00Section *psSectionIn )
43 2 : : OGRAVCLayer( psSectionIn->eType, poDSIn )
44 :
45 : {
46 2 : psSection = psSectionIn;
47 2 : hFile = NULL;
48 2 : poArcLayer = NULL;
49 2 : bNeedReset = FALSE;
50 2 : nNextFID = 1;
51 :
52 2 : hTable = NULL;
53 2 : nTableBaseField = -1;
54 2 : nTableAttrIndex = -1;
55 :
56 2 : SetupFeatureDefinition( psSection->pszName );
57 :
58 2 : szTableName[0] = '\0';
59 2 : if( psSection->eType == AVCFilePAL )
60 0 : sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
61 2 : else if( psSection->eType == AVCFileRPL )
62 : sprintf( szTableName, "%s.PAT%s", poDS->GetCoverageName(),
63 0 : psSectionIn->pszName );
64 2 : else if( psSection->eType == AVCFileARC )
65 1 : sprintf( szTableName, "%s.AAT", poDS->GetCoverageName() );
66 1 : else if( psSection->eType == AVCFileLAB )
67 : {
68 1 : AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
69 :
70 1 : sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
71 :
72 13 : for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
73 : {
74 12 : if( psInfo->pasSections[iSection].eType == AVCFilePAL )
75 0 : nTableAttrIndex = poFeatureDefn->GetFieldIndex( "PolyId" );
76 : }
77 : }
78 :
79 2 : CheckSetupTable();
80 2 : }
81 :
82 : /************************************************************************/
83 : /* ~OGRAVCBinLayer() */
84 : /************************************************************************/
85 :
86 4 : OGRAVCBinLayer::~OGRAVCBinLayer()
87 :
88 : {
89 2 : ResetReading();
90 4 : }
91 :
92 : /************************************************************************/
93 : /* ResetReading() */
94 : /************************************************************************/
95 :
96 4 : void OGRAVCBinLayer::ResetReading()
97 :
98 : {
99 4 : if( hFile != NULL )
100 : {
101 2 : AVCBinReadClose( hFile );
102 2 : hFile = NULL;
103 : }
104 :
105 4 : bNeedReset = FALSE;
106 4 : nNextFID = 1;
107 :
108 4 : if( hTable != NULL )
109 : {
110 0 : AVCBinReadClose( hTable );
111 0 : hTable = NULL;
112 : }
113 4 : }
114 :
115 : /************************************************************************/
116 : /* GetFeature() */
117 : /************************************************************************/
118 :
119 9 : OGRFeature *OGRAVCBinLayer::GetFeature( long nFID )
120 :
121 : {
122 : /* -------------------------------------------------------------------- */
123 : /* If we haven't started yet, open the file now. */
124 : /* -------------------------------------------------------------------- */
125 9 : if( hFile == NULL )
126 : {
127 2 : AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
128 :
129 : hFile = AVCBinReadOpen(psInfo->pszCoverPath,
130 : psSection->pszFilename,
131 : psInfo->eCoverType,
132 : psSection->eType,
133 2 : psInfo->psDBCSInfo);
134 : }
135 :
136 : /* -------------------------------------------------------------------- */
137 : /* Read the raw feature - the -3 fid is a special flag */
138 : /* indicating serial access. */
139 : /* -------------------------------------------------------------------- */
140 : void *pFeature;
141 :
142 9 : if( nFID == -3 )
143 : {
144 18 : while( (pFeature = AVCBinReadNextObject( hFile )) != NULL
145 : && !MatchesSpatialFilter( pFeature ) )
146 : {
147 0 : nNextFID++;
148 : }
149 : }
150 : else
151 : {
152 0 : bNeedReset = TRUE;
153 0 : pFeature = AVCBinReadObject( hFile, nFID );
154 : }
155 :
156 9 : if( pFeature == NULL )
157 1 : return NULL;
158 :
159 : /* -------------------------------------------------------------------- */
160 : /* Translate the feature. */
161 : /* -------------------------------------------------------------------- */
162 : OGRFeature *poFeature;
163 :
164 8 : poFeature = TranslateFeature( pFeature );
165 8 : if( poFeature == NULL )
166 0 : return NULL;
167 :
168 : /* -------------------------------------------------------------------- */
169 : /* LAB's we have to assign the FID to directly, since it */
170 : /* doesn't seem to be stored in the file structure. */
171 : /* -------------------------------------------------------------------- */
172 8 : if( psSection->eType == AVCFileLAB )
173 : {
174 0 : if( nFID == -3 )
175 0 : poFeature->SetFID( nNextFID++ );
176 : else
177 0 : poFeature->SetFID( nFID );
178 : }
179 :
180 : /* -------------------------------------------------------------------- */
181 : /* If this is a polygon layer, try to assemble the arcs to form */
182 : /* the whole polygon geometry. */
183 : /* -------------------------------------------------------------------- */
184 8 : if( psSection->eType == AVCFilePAL
185 : || psSection->eType == AVCFileRPL )
186 0 : FormPolygonGeometry( poFeature, (AVCPal *) pFeature );
187 :
188 : /* -------------------------------------------------------------------- */
189 : /* If we have an attribute table, append the attributes now. */
190 : /* -------------------------------------------------------------------- */
191 8 : AppendTableFields( poFeature );
192 :
193 8 : return poFeature;
194 : }
195 :
196 : /************************************************************************/
197 : /* GetNextFeature() */
198 : /************************************************************************/
199 :
200 9 : OGRFeature *OGRAVCBinLayer::GetNextFeature()
201 :
202 : {
203 9 : if( bNeedReset )
204 0 : ResetReading();
205 :
206 9 : OGRFeature *poFeature = GetFeature( -3 );
207 :
208 : // Skip universe polygon.
209 9 : if( poFeature != NULL && poFeature->GetFID() == 1
210 : && psSection->eType == AVCFilePAL )
211 : {
212 0 : OGRFeature::DestroyFeature( poFeature );
213 0 : poFeature = GetFeature( -3 );
214 : }
215 :
216 18 : while( poFeature != NULL
217 : && ((m_poAttrQuery != NULL
218 : && !m_poAttrQuery->Evaluate( poFeature ) )
219 : || !FilterGeometry( poFeature->GetGeometryRef() ) ) )
220 : {
221 0 : OGRFeature::DestroyFeature( poFeature );
222 0 : poFeature = GetFeature( -3 );
223 : }
224 :
225 9 : if( poFeature == NULL )
226 1 : ResetReading();
227 :
228 9 : return poFeature;
229 : }
230 :
231 : /************************************************************************/
232 : /* TestCapability() */
233 : /************************************************************************/
234 :
235 0 : int OGRAVCBinLayer::TestCapability( const char * pszCap )
236 :
237 : {
238 0 : if( eSectionType == AVCFileARC && EQUAL(pszCap,OLCRandomRead) )
239 0 : return TRUE;
240 : else
241 0 : return OGRAVCLayer::TestCapability( pszCap );
242 : }
243 :
244 : /************************************************************************/
245 : /* FormPolygonGeometry() */
246 : /* */
247 : /* Collect all the arcs forming edges to this polygon and form */
248 : /* them into the appropriate OGR geometry on the target feature. */
249 : /************************************************************************/
250 :
251 0 : int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
252 : AVCPal *psPAL )
253 :
254 : {
255 : /* -------------------------------------------------------------------- */
256 : /* Try to find the corresponding ARC layer if not already */
257 : /* recorded. */
258 : /* -------------------------------------------------------------------- */
259 0 : if( poArcLayer == NULL )
260 : {
261 : int i;
262 :
263 0 : for( i = 0; i < poDS->GetLayerCount(); i++ )
264 : {
265 0 : OGRAVCBinLayer *poLayer = (OGRAVCBinLayer *) poDS->GetLayer(i);
266 :
267 0 : if( poLayer->eSectionType == AVCFileARC )
268 0 : poArcLayer = poLayer;
269 : }
270 :
271 0 : if( poArcLayer == NULL )
272 0 : return FALSE;
273 : }
274 :
275 : /* -------------------------------------------------------------------- */
276 : /* Read all the arcs related to this polygon, making a working */
277 : /* copy of them since the one returned by AVC is temporary. */
278 : /* -------------------------------------------------------------------- */
279 0 : OGRGeometryCollection oArcs;
280 : int iArc;
281 :
282 0 : for( iArc = 0; iArc < psPAL->numArcs; iArc++ )
283 : {
284 : OGRFeature *poArc;
285 :
286 0 : if( psPAL->pasArcs[iArc].nArcId == 0 )
287 0 : continue;
288 :
289 : // If the other side of the line is the same polygon then this
290 : // arc is a "bridge" arc and can be discarded. If we don't discard
291 : // it, then we should double it as bridge arcs seem to only appear
292 : // once. But by discarding it we ensure a multi-ring polygon will be
293 : // properly formed.
294 0 : if( psPAL->pasArcs[iArc].nAdjPoly == psPAL->nPolyId )
295 0 : continue;
296 :
297 0 : poArc = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
298 :
299 0 : if( poArc == NULL )
300 0 : return FALSE;
301 :
302 0 : if( poArc->GetGeometryRef() == NULL )
303 0 : return FALSE;
304 :
305 0 : oArcs.addGeometry( poArc->GetGeometryRef() );
306 0 : OGRFeature::DestroyFeature( poArc );
307 : }
308 :
309 : OGRErr eErr;
310 : OGRPolygon *poPolygon;
311 :
312 : poPolygon = (OGRPolygon *)
313 : OGRBuildPolygonFromEdges( (OGRGeometryH) &oArcs, TRUE, FALSE,
314 0 : 0.0, &eErr );
315 0 : if( poPolygon != NULL )
316 0 : poFeature->SetGeometryDirectly( poPolygon );
317 :
318 0 : return eErr == OGRERR_NONE;
319 : }
320 :
321 : /************************************************************************/
322 : /* CheckSetupTable() */
323 : /* */
324 : /* Check if the named table exists, and if so, setup access to */
325 : /* it (open it), and add it's fields to the feature class */
326 : /* definition. */
327 : /************************************************************************/
328 :
329 2 : int OGRAVCBinLayer::CheckSetupTable()
330 :
331 : {
332 2 : if( szTableName[0] == '\0' )
333 0 : return FALSE;
334 :
335 : /* -------------------------------------------------------------------- */
336 : /* Scan for the indicated section. */
337 : /* -------------------------------------------------------------------- */
338 2 : AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
339 : int iSection;
340 2 : AVCE00Section *psSection = NULL;
341 : char szPaddedName[65];
342 :
343 2 : sprintf( szPaddedName, "%s%32s", szTableName, " " );
344 2 : szPaddedName[32] = '\0';
345 :
346 26 : for( iSection = 0; iSection < psInfo->numSections; iSection++ )
347 : {
348 24 : if( EQUAL(szPaddedName,psInfo->pasSections[iSection].pszName)
349 0 : && psInfo->pasSections[iSection].eType == AVCFileTABLE )
350 0 : psSection = psInfo->pasSections + iSection;
351 : }
352 :
353 2 : if( psSection == NULL )
354 : {
355 2 : szTableName[0] = '\0';
356 2 : return FALSE;
357 : }
358 :
359 : /* -------------------------------------------------------------------- */
360 : /* Try opening the table. */
361 : /* -------------------------------------------------------------------- */
362 : hTable = AVCBinReadOpen( psInfo->pszInfoPath, szTableName,
363 : psInfo->eCoverType, AVCFileTABLE,
364 0 : psInfo->psDBCSInfo);
365 :
366 0 : if( hTable == NULL )
367 : {
368 0 : szTableName[0] = '\0';
369 0 : return FALSE;
370 : }
371 :
372 : /* -------------------------------------------------------------------- */
373 : /* Setup attributes. */
374 : /* -------------------------------------------------------------------- */
375 0 : nTableBaseField = poFeatureDefn->GetFieldCount();
376 :
377 0 : AppendTableDefinition( hTable->hdr.psTableDef );
378 :
379 : /* -------------------------------------------------------------------- */
380 : /* Close table so we don't have to many files open at once. */
381 : /* -------------------------------------------------------------------- */
382 0 : AVCBinReadClose( hTable );
383 :
384 0 : hTable = NULL;
385 :
386 0 : return TRUE;
387 : }
388 :
389 : /************************************************************************/
390 : /* AppendTableFields() */
391 : /************************************************************************/
392 :
393 8 : int OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
394 :
395 : {
396 8 : AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
397 :
398 8 : if( szTableName[0] == '\0' )
399 8 : return FALSE;
400 :
401 : /* -------------------------------------------------------------------- */
402 : /* Open the table if it is currently closed. */
403 : /* -------------------------------------------------------------------- */
404 0 : if( hTable == NULL )
405 : {
406 : hTable = AVCBinReadOpen( psInfo->pszInfoPath, szTableName,
407 : psInfo->eCoverType, AVCFileTABLE,
408 0 : psInfo->psDBCSInfo);
409 : }
410 :
411 0 : if( hTable == NULL )
412 0 : return FALSE;
413 :
414 : /* -------------------------------------------------------------------- */
415 : /* Read the info record. */
416 : /* */
417 : /* We usually assume the FID of the feature is the key but in a */
418 : /* polygon coverage we need to use the PolyId attribute of LAB */
419 : /* features to lookup the related attributes. In this case */
420 : /* nTableAttrIndex will already be setup to refer to the */
421 : /* PolyId field. */
422 : /* -------------------------------------------------------------------- */
423 : int nRecordId;
424 : void *hRecord;
425 :
426 0 : if( nTableAttrIndex == -1 )
427 0 : nRecordId = poFeature->GetFID();
428 : else
429 0 : nRecordId = poFeature->GetFieldAsInteger( nTableAttrIndex );
430 :
431 0 : hRecord = AVCBinReadObject( hTable, nRecordId );
432 0 : if( hRecord == NULL )
433 0 : return FALSE;
434 :
435 : /* -------------------------------------------------------------------- */
436 : /* Translate it. */
437 : /* -------------------------------------------------------------------- */
438 : return TranslateTableFields( poFeature, nTableBaseField,
439 : hTable->hdr.psTableDef,
440 0 : (AVCField *) hRecord );
441 : }
442 :
443 :
444 :
445 :
446 :
|