1 : /******************************************************************************
2 : * $Id: ogrsdtslayer.cpp 19952 2010-07-02 05:44:18Z warmerdam $
3 : *
4 : * Project: SDTSReader
5 : * Purpose: Implements OGRSDTSLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
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_sdts.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ogrsdtslayer.cpp 19952 2010-07-02 05:44:18Z warmerdam $");
35 :
36 : /************************************************************************/
37 : /* OGRSDTSLayer() */
38 : /* */
39 : /* Note that the OGRSDTSLayer assumes ownership of the passed */
40 : /* OGRFeatureDefn object. */
41 : /************************************************************************/
42 :
43 16 : OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
44 16 : OGRSDTSDataSource * poDSIn )
45 :
46 : {
47 16 : poDS = poDSIn;
48 :
49 16 : poTransfer = poTransferIn;
50 16 : iLayer = iLayerIn;
51 :
52 16 : poReader = poTransfer->GetLayerIndexedReader( iLayer );
53 :
54 : /* -------------------------------------------------------------------- */
55 : /* Define the feature. */
56 : /* -------------------------------------------------------------------- */
57 16 : int iCATDEntry = poTransfer->GetLayerCATDEntry( iLayer );
58 :
59 : poFeatureDefn =
60 16 : new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
61 16 : poFeatureDefn->Reference();
62 :
63 16 : OGRFieldDefn oRecId( "RCID", OFTInteger );
64 16 : poFeatureDefn->AddFieldDefn( &oRecId );
65 :
66 16 : if( poTransfer->GetLayerType(iLayer) == SLTPoint )
67 : {
68 6 : poFeatureDefn->SetGeomType( wkbPoint );
69 : }
70 10 : else if( poTransfer->GetLayerType(iLayer) == SLTLine )
71 : {
72 2 : poFeatureDefn->SetGeomType( wkbLineString );
73 :
74 2 : oRecId.SetName( "SNID" );
75 2 : poFeatureDefn->AddFieldDefn( &oRecId );
76 :
77 2 : oRecId.SetName( "ENID" );
78 2 : poFeatureDefn->AddFieldDefn( &oRecId );
79 : }
80 8 : else if( poTransfer->GetLayerType(iLayer) == SLTPoly )
81 : {
82 2 : poFeatureDefn->SetGeomType( wkbPolygon );
83 : }
84 6 : else if( poTransfer->GetLayerType(iLayer) == SLTAttr )
85 : {
86 6 : poFeatureDefn->SetGeomType( wkbNone );
87 : }
88 :
89 : /* -------------------------------------------------------------------- */
90 : /* Add schema from referenced attribute records. */
91 : /* -------------------------------------------------------------------- */
92 16 : char **papszATIDRefs = NULL;
93 :
94 16 : if( poTransfer->GetLayerType(iLayer) != SLTAttr )
95 10 : papszATIDRefs = poReader->ScanModuleReferences();
96 : else
97 : papszATIDRefs = CSLAddString( papszATIDRefs,
98 6 : poTransfer->GetCATD()->GetEntryModule(iCATDEntry) );
99 :
100 40 : for( int iTable = 0;
101 16 : papszATIDRefs != NULL && papszATIDRefs[iTable] != NULL;
102 : iTable++ )
103 : {
104 : SDTSAttrReader *poAttrReader;
105 : DDFFieldDefn *poFDefn;
106 :
107 : /* -------------------------------------------------------------------- */
108 : /* Get the attribute table reader, and the associated user */
109 : /* attribute field. */
110 : /* -------------------------------------------------------------------- */
111 : poAttrReader = (SDTSAttrReader *)
112 : poTransfer->GetLayerIndexedReader(
113 8 : poTransfer->FindLayer( papszATIDRefs[iTable] ) );
114 :
115 8 : if( poAttrReader == NULL )
116 0 : continue;
117 :
118 8 : poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTP" );
119 8 : if( poFDefn == NULL )
120 0 : poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTS" );
121 8 : if( poFDefn == NULL )
122 0 : continue;
123 :
124 : /* -------------------------------------------------------------------- */
125 : /* Process each user subfield on the attribute table into an */
126 : /* OGR field definition. */
127 : /* -------------------------------------------------------------------- */
128 128 : for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
129 : {
130 120 : DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
131 120 : int nWidth = poSFDefn->GetWidth();
132 : char *pszFieldName;
133 :
134 120 : if( poFeatureDefn->GetFieldIndex( poSFDefn->GetName() ) != -1 )
135 : pszFieldName = CPLStrdup( CPLSPrintf( "%s_%s",
136 : papszATIDRefs[iTable],
137 0 : poSFDefn->GetName() ) );
138 : else
139 120 : pszFieldName = CPLStrdup( poSFDefn->GetName() );
140 :
141 120 : switch( poSFDefn->GetType() )
142 : {
143 : case DDFString:
144 : {
145 88 : OGRFieldDefn oStrField( pszFieldName, OFTString );
146 :
147 88 : if( nWidth != 0 )
148 88 : oStrField.SetWidth( nWidth );
149 :
150 88 : poFeatureDefn->AddFieldDefn( &oStrField );
151 : }
152 88 : break;
153 :
154 : case DDFInt:
155 : {
156 8 : OGRFieldDefn oIntField( pszFieldName, OFTInteger );
157 :
158 8 : if( nWidth != 0 )
159 8 : oIntField.SetWidth( nWidth );
160 :
161 8 : poFeatureDefn->AddFieldDefn( &oIntField );
162 : }
163 8 : break;
164 :
165 : case DDFFloat:
166 : {
167 24 : OGRFieldDefn oRealField( pszFieldName, OFTReal );
168 :
169 : // We don't have a precision in DDF files, so we never even
170 : // use the width. Otherwise with a precision of zero the
171 : // result would look like an integer.
172 :
173 24 : poFeatureDefn->AddFieldDefn( &oRealField );
174 : }
175 : break;
176 :
177 : default:
178 : break;
179 : }
180 :
181 120 : CPLFree( pszFieldName );
182 :
183 : } /* next iSF (subfield) */
184 : } /* next iTable */
185 16 : CSLDestroy( papszATIDRefs );
186 16 : }
187 :
188 : /************************************************************************/
189 : /* ~OGRSDTSLayer() */
190 : /************************************************************************/
191 :
192 16 : OGRSDTSLayer::~OGRSDTSLayer()
193 :
194 : {
195 16 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
196 : {
197 : CPLDebug( "SDTS", "%d features read on layer '%s'.",
198 : (int) m_nFeaturesRead,
199 16 : poFeatureDefn->GetName() );
200 : }
201 :
202 16 : if( poFeatureDefn )
203 16 : poFeatureDefn->Release();
204 16 : }
205 :
206 : /************************************************************************/
207 : /* ResetReading() */
208 : /************************************************************************/
209 :
210 32 : void OGRSDTSLayer::ResetReading()
211 :
212 : {
213 32 : poReader->Rewind();
214 32 : }
215 :
216 : /************************************************************************/
217 : /* AssignAttrRecordToFeature() */
218 : /************************************************************************/
219 :
220 : static void
221 390 : AssignAttrRecordToFeature( OGRFeature * poFeature, SDTSTransfer * poTransfer,
222 : DDFField * poSR )
223 :
224 : {
225 : /* -------------------------------------------------------------------- */
226 : /* Process each subfield in the record. */
227 : /* -------------------------------------------------------------------- */
228 390 : DDFFieldDefn *poFDefn = poSR->GetFieldDefn();
229 :
230 6054 : for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
231 : {
232 5664 : DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
233 : int iField;
234 : int nMaxBytes;
235 : const char * pachData = poSR->GetSubfieldData(poSFDefn,
236 5664 : &nMaxBytes);
237 : /* -------------------------------------------------------------------- */
238 : /* Indentify this field on the feature. */
239 : /* -------------------------------------------------------------------- */
240 5664 : iField = poFeature->GetFieldIndex( poSFDefn->GetName() );
241 :
242 : /* -------------------------------------------------------------------- */
243 : /* Handle each of the types. */
244 : /* -------------------------------------------------------------------- */
245 5664 : switch( poSFDefn->GetType() )
246 : {
247 : case DDFString:
248 : const char *pszValue;
249 :
250 : pszValue = poSFDefn->ExtractStringData(pachData, nMaxBytes,
251 4932 : NULL);
252 :
253 4932 : if( iField != -1 )
254 4932 : poFeature->SetField( iField, pszValue );
255 4932 : break;
256 :
257 : case DDFFloat:
258 : double dfValue;
259 :
260 : dfValue = poSFDefn->ExtractFloatData(pachData, nMaxBytes,
261 48 : NULL);
262 :
263 48 : if( iField != -1 )
264 48 : poFeature->SetField( iField, dfValue );
265 48 : break;
266 :
267 : case DDFInt:
268 : int nValue;
269 :
270 684 : nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL);
271 :
272 684 : if( iField != -1 )
273 684 : poFeature->SetField( iField, nValue );
274 : break;
275 :
276 : default:
277 : break;
278 : }
279 : } /* next subfield */
280 390 : }
281 :
282 : /************************************************************************/
283 : /* GetNextUnfilteredFeature() */
284 : /************************************************************************/
285 :
286 780 : OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
287 :
288 : {
289 : /* -------------------------------------------------------------------- */
290 : /* If not done before we need to assemble the geometry for a */
291 : /* polygon layer. */
292 : /* -------------------------------------------------------------------- */
293 780 : if( poTransfer->GetLayerType(iLayer) == SLTPoly )
294 : {
295 74 : ((SDTSPolygonReader *) poReader)->AssembleRings(poTransfer,iLayer);
296 : }
297 :
298 : /* -------------------------------------------------------------------- */
299 : /* Fetch the next sdts style feature object from the reader. */
300 : /* -------------------------------------------------------------------- */
301 780 : SDTSFeature *poSDTSFeature = poReader->GetNextFeature();
302 : OGRFeature *poFeature;
303 :
304 780 : if( poSDTSFeature == NULL )
305 16 : return NULL;
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Create the OGR feature. */
309 : /* -------------------------------------------------------------------- */
310 764 : poFeature = new OGRFeature( poFeatureDefn );
311 :
312 764 : m_nFeaturesRead++;
313 :
314 764 : switch( poTransfer->GetLayerType(iLayer) )
315 : {
316 : /* -------------------------------------------------------------------- */
317 : /* Translate point feature specific information and geometry. */
318 : /* -------------------------------------------------------------------- */
319 : case SLTPoint:
320 : {
321 258 : SDTSRawPoint *poPoint = (SDTSRawPoint *) poSDTSFeature;
322 :
323 : poFeature->SetGeometryDirectly( new OGRPoint( poPoint->dfX,
324 : poPoint->dfY,
325 258 : poPoint->dfZ ) );
326 : }
327 258 : break;
328 :
329 : /* -------------------------------------------------------------------- */
330 : /* Translate line feature specific information and geometry. */
331 : /* -------------------------------------------------------------------- */
332 : case SLTLine:
333 : {
334 56 : SDTSRawLine *poLine = (SDTSRawLine *) poSDTSFeature;
335 56 : OGRLineString *poOGRLine = new OGRLineString();
336 :
337 : poOGRLine->setPoints( poLine->nVertices,
338 56 : poLine->padfX, poLine->padfY, poLine->padfZ );
339 56 : poFeature->SetGeometryDirectly( poOGRLine );
340 56 : poFeature->SetField( "SNID", (int) poLine->oStartNode.nRecord );
341 56 : poFeature->SetField( "ENID", (int) poLine->oEndNode.nRecord );
342 : }
343 56 : break;
344 :
345 : /* -------------------------------------------------------------------- */
346 : /* Translate polygon feature specific information and geometry. */
347 : /* -------------------------------------------------------------------- */
348 : case SLTPoly:
349 : {
350 72 : SDTSRawPolygon *poPoly = (SDTSRawPolygon *) poSDTSFeature;
351 72 : OGRPolygon *poOGRPoly = new OGRPolygon();
352 :
353 108 : for( int iRing = 0; iRing < poPoly->nRings; iRing++ )
354 : {
355 36 : OGRLinearRing *poRing = new OGRLinearRing();
356 : int nVertices;
357 :
358 36 : if( iRing == poPoly->nRings - 1 )
359 28 : nVertices = poPoly->nVertices - poPoly->panRingStart[iRing];
360 : else
361 8 : nVertices = poPoly->panRingStart[iRing+1]
362 8 : - poPoly->panRingStart[iRing];
363 :
364 : poRing->setPoints( nVertices,
365 36 : poPoly->padfX + poPoly->panRingStart[iRing],
366 36 : poPoly->padfY + poPoly->panRingStart[iRing],
367 108 : poPoly->padfZ + poPoly->panRingStart[iRing] );
368 :
369 36 : poOGRPoly->addRingDirectly( poRing );
370 : }
371 :
372 72 : poFeature->SetGeometryDirectly( poOGRPoly );
373 : }
374 : break;
375 :
376 : default:
377 : break;
378 : }
379 :
380 : /* -------------------------------------------------------------------- */
381 : /* Set attributes for any indicated attribute records. */
382 : /* -------------------------------------------------------------------- */
383 : int iAttrRecord;
384 :
385 776 : for( iAttrRecord = 0;
386 : iAttrRecord < poSDTSFeature->nAttributes;
387 : iAttrRecord++)
388 : {
389 : DDFField *poSR;
390 :
391 12 : poSR = poTransfer->GetAttr( poSDTSFeature->paoATID+iAttrRecord );
392 :
393 12 : AssignAttrRecordToFeature( poFeature, poTransfer, poSR );
394 : }
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* If this record is an attribute record, attach the local */
398 : /* attributes. */
399 : /* -------------------------------------------------------------------- */
400 764 : if( poTransfer->GetLayerType(iLayer) == SLTAttr )
401 : {
402 : AssignAttrRecordToFeature( poFeature, poTransfer,
403 378 : ((SDTSAttrRecord *) poSDTSFeature)->poATTR);
404 : }
405 :
406 : /* -------------------------------------------------------------------- */
407 : /* Translate the record id. */
408 : /* -------------------------------------------------------------------- */
409 764 : poFeature->SetFID( poSDTSFeature->oModId.nRecord );
410 764 : poFeature->SetField( 0, (int) poSDTSFeature->oModId.nRecord );
411 764 : if( poFeature->GetGeometryRef() != NULL )
412 : poFeature->GetGeometryRef()->assignSpatialReference(
413 386 : poDS->GetSpatialRef() );
414 :
415 764 : if( !poReader->IsIndexed() )
416 692 : delete poSDTSFeature;
417 :
418 764 : return poFeature;
419 : }
420 :
421 :
422 : /************************************************************************/
423 : /* GetNextFeature() */
424 : /************************************************************************/
425 :
426 780 : OGRFeature *OGRSDTSLayer::GetNextFeature()
427 :
428 : {
429 780 : OGRFeature *poFeature = NULL;
430 :
431 : /* -------------------------------------------------------------------- */
432 : /* Read features till we find one that satisfies our current */
433 : /* spatial criteria. */
434 : /* -------------------------------------------------------------------- */
435 0 : while( TRUE )
436 : {
437 780 : poFeature = GetNextUnfilteredFeature();
438 780 : if( poFeature == NULL )
439 16 : break;
440 :
441 764 : if( (m_poFilterGeom == NULL
442 : || FilterGeometry( poFeature->GetGeometryRef() ) )
443 : && (m_poAttrQuery == NULL
444 : || m_poAttrQuery->Evaluate( poFeature )) )
445 764 : break;
446 :
447 0 : delete poFeature;
448 : }
449 :
450 780 : return poFeature;
451 : }
452 :
453 : /************************************************************************/
454 : /* TestCapability() */
455 : /************************************************************************/
456 :
457 0 : int OGRSDTSLayer::TestCapability( const char * pszCap )
458 :
459 : {
460 0 : if( EQUAL(pszCap,OLCRandomRead) )
461 0 : return FALSE;
462 :
463 0 : else if( EQUAL(pszCap,OLCSequentialWrite)
464 : || EQUAL(pszCap,OLCRandomWrite) )
465 0 : return FALSE;
466 :
467 0 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
468 0 : return FALSE;
469 :
470 0 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
471 0 : return FALSE;
472 :
473 : else
474 0 : return FALSE;
475 : }
476 :
477 :
478 : /************************************************************************/
479 : /* GetSpatialRef() */
480 : /************************************************************************/
481 :
482 0 : OGRSpatialReference * OGRSDTSLayer::GetSpatialRef()
483 :
484 : {
485 0 : return poDS->GetSpatialRef();
486 : }
|