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 8 : OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
44 8 : OGRSDTSDataSource * poDSIn )
45 :
46 : {
47 8 : poDS = poDSIn;
48 :
49 8 : poTransfer = poTransferIn;
50 8 : iLayer = iLayerIn;
51 :
52 8 : poReader = poTransfer->GetLayerIndexedReader( iLayer );
53 :
54 : /* -------------------------------------------------------------------- */
55 : /* Define the feature. */
56 : /* -------------------------------------------------------------------- */
57 8 : int iCATDEntry = poTransfer->GetLayerCATDEntry( iLayer );
58 :
59 : poFeatureDefn =
60 8 : new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
61 8 : poFeatureDefn->Reference();
62 :
63 8 : OGRFieldDefn oRecId( "RCID", OFTInteger );
64 8 : poFeatureDefn->AddFieldDefn( &oRecId );
65 :
66 8 : if( poTransfer->GetLayerType(iLayer) == SLTPoint )
67 : {
68 3 : poFeatureDefn->SetGeomType( wkbPoint );
69 : }
70 5 : else if( poTransfer->GetLayerType(iLayer) == SLTLine )
71 : {
72 1 : poFeatureDefn->SetGeomType( wkbLineString );
73 :
74 1 : oRecId.SetName( "SNID" );
75 1 : poFeatureDefn->AddFieldDefn( &oRecId );
76 :
77 1 : oRecId.SetName( "ENID" );
78 1 : poFeatureDefn->AddFieldDefn( &oRecId );
79 : }
80 4 : else if( poTransfer->GetLayerType(iLayer) == SLTPoly )
81 : {
82 1 : poFeatureDefn->SetGeomType( wkbPolygon );
83 : }
84 3 : else if( poTransfer->GetLayerType(iLayer) == SLTAttr )
85 : {
86 3 : poFeatureDefn->SetGeomType( wkbNone );
87 : }
88 :
89 : /* -------------------------------------------------------------------- */
90 : /* Add schema from referenced attribute records. */
91 : /* -------------------------------------------------------------------- */
92 8 : char **papszATIDRefs = NULL;
93 :
94 8 : if( poTransfer->GetLayerType(iLayer) != SLTAttr )
95 5 : papszATIDRefs = poReader->ScanModuleReferences();
96 : else
97 : papszATIDRefs = CSLAddString( papszATIDRefs,
98 3 : poTransfer->GetCATD()->GetEntryModule(iCATDEntry) );
99 :
100 20 : for( int iTable = 0;
101 8 : 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 4 : poTransfer->FindLayer( papszATIDRefs[iTable] ) );
114 :
115 4 : if( poAttrReader == NULL )
116 0 : continue;
117 :
118 4 : poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTP" );
119 4 : if( poFDefn == NULL )
120 0 : poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTS" );
121 4 : 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 64 : for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
129 : {
130 60 : DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
131 60 : int nWidth = poSFDefn->GetWidth();
132 : char *pszFieldName;
133 :
134 60 : if( poFeatureDefn->GetFieldIndex( poSFDefn->GetName() ) != -1 )
135 : pszFieldName = CPLStrdup( CPLSPrintf( "%s_%s",
136 : papszATIDRefs[iTable],
137 0 : poSFDefn->GetName() ) );
138 : else
139 60 : pszFieldName = CPLStrdup( poSFDefn->GetName() );
140 :
141 60 : switch( poSFDefn->GetType() )
142 : {
143 : case DDFString:
144 : {
145 44 : OGRFieldDefn oStrField( pszFieldName, OFTString );
146 :
147 44 : if( nWidth != 0 )
148 44 : oStrField.SetWidth( nWidth );
149 :
150 44 : poFeatureDefn->AddFieldDefn( &oStrField );
151 : }
152 44 : break;
153 :
154 : case DDFInt:
155 : {
156 4 : OGRFieldDefn oIntField( pszFieldName, OFTInteger );
157 :
158 4 : if( nWidth != 0 )
159 4 : oIntField.SetWidth( nWidth );
160 :
161 4 : poFeatureDefn->AddFieldDefn( &oIntField );
162 : }
163 4 : break;
164 :
165 : case DDFFloat:
166 : {
167 12 : 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 12 : poFeatureDefn->AddFieldDefn( &oRealField );
174 : }
175 : break;
176 :
177 : default:
178 : break;
179 : }
180 :
181 60 : CPLFree( pszFieldName );
182 :
183 : } /* next iSF (subfield) */
184 : } /* next iTable */
185 8 : CSLDestroy( papszATIDRefs );
186 8 : }
187 :
188 : /************************************************************************/
189 : /* ~OGRSDTSLayer() */
190 : /************************************************************************/
191 :
192 8 : OGRSDTSLayer::~OGRSDTSLayer()
193 :
194 : {
195 8 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
196 : {
197 : CPLDebug( "SDTS", "%d features read on layer '%s'.",
198 : (int) m_nFeaturesRead,
199 8 : poFeatureDefn->GetName() );
200 : }
201 :
202 8 : if( poFeatureDefn )
203 8 : poFeatureDefn->Release();
204 8 : }
205 :
206 : /************************************************************************/
207 : /* ResetReading() */
208 : /************************************************************************/
209 :
210 16 : void OGRSDTSLayer::ResetReading()
211 :
212 : {
213 16 : poReader->Rewind();
214 16 : }
215 :
216 : /************************************************************************/
217 : /* AssignAttrRecordToFeature() */
218 : /************************************************************************/
219 :
220 : static void
221 195 : AssignAttrRecordToFeature( OGRFeature * poFeature, SDTSTransfer * poTransfer,
222 : DDFField * poSR )
223 :
224 : {
225 : /* -------------------------------------------------------------------- */
226 : /* Process each subfield in the record. */
227 : /* -------------------------------------------------------------------- */
228 195 : DDFFieldDefn *poFDefn = poSR->GetFieldDefn();
229 :
230 3027 : for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
231 : {
232 2832 : DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
233 : int iField;
234 : int nMaxBytes;
235 : const char * pachData = poSR->GetSubfieldData(poSFDefn,
236 2832 : &nMaxBytes);
237 : /* -------------------------------------------------------------------- */
238 : /* Indentify this field on the feature. */
239 : /* -------------------------------------------------------------------- */
240 2832 : iField = poFeature->GetFieldIndex( poSFDefn->GetName() );
241 :
242 : /* -------------------------------------------------------------------- */
243 : /* Handle each of the types. */
244 : /* -------------------------------------------------------------------- */
245 2832 : switch( poSFDefn->GetType() )
246 : {
247 : case DDFString:
248 : const char *pszValue;
249 :
250 : pszValue = poSFDefn->ExtractStringData(pachData, nMaxBytes,
251 2466 : NULL);
252 :
253 2466 : if( iField != -1 )
254 2466 : poFeature->SetField( iField, pszValue );
255 2466 : break;
256 :
257 : case DDFFloat:
258 : double dfValue;
259 :
260 : dfValue = poSFDefn->ExtractFloatData(pachData, nMaxBytes,
261 24 : NULL);
262 :
263 24 : if( iField != -1 )
264 24 : poFeature->SetField( iField, dfValue );
265 24 : break;
266 :
267 : case DDFInt:
268 : int nValue;
269 :
270 342 : nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL);
271 :
272 342 : if( iField != -1 )
273 342 : poFeature->SetField( iField, nValue );
274 : break;
275 :
276 : default:
277 : break;
278 : }
279 : } /* next subfield */
280 195 : }
281 :
282 : /************************************************************************/
283 : /* GetNextUnfilteredFeature() */
284 : /************************************************************************/
285 :
286 390 : OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
287 :
288 : {
289 : /* -------------------------------------------------------------------- */
290 : /* If not done before we need to assemble the geometry for a */
291 : /* polygon layer. */
292 : /* -------------------------------------------------------------------- */
293 390 : if( poTransfer->GetLayerType(iLayer) == SLTPoly )
294 : {
295 37 : ((SDTSPolygonReader *) poReader)->AssembleRings(poTransfer,iLayer);
296 : }
297 :
298 : /* -------------------------------------------------------------------- */
299 : /* Fetch the next sdts style feature object from the reader. */
300 : /* -------------------------------------------------------------------- */
301 390 : SDTSFeature *poSDTSFeature = poReader->GetNextFeature();
302 : OGRFeature *poFeature;
303 :
304 390 : if( poSDTSFeature == NULL )
305 8 : return NULL;
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Create the OGR feature. */
309 : /* -------------------------------------------------------------------- */
310 382 : poFeature = new OGRFeature( poFeatureDefn );
311 :
312 382 : m_nFeaturesRead++;
313 :
314 382 : switch( poTransfer->GetLayerType(iLayer) )
315 : {
316 : /* -------------------------------------------------------------------- */
317 : /* Translate point feature specific information and geometry. */
318 : /* -------------------------------------------------------------------- */
319 : case SLTPoint:
320 : {
321 129 : SDTSRawPoint *poPoint = (SDTSRawPoint *) poSDTSFeature;
322 :
323 : poFeature->SetGeometryDirectly( new OGRPoint( poPoint->dfX,
324 : poPoint->dfY,
325 129 : poPoint->dfZ ) );
326 : }
327 129 : break;
328 :
329 : /* -------------------------------------------------------------------- */
330 : /* Translate line feature specific information and geometry. */
331 : /* -------------------------------------------------------------------- */
332 : case SLTLine:
333 : {
334 28 : SDTSRawLine *poLine = (SDTSRawLine *) poSDTSFeature;
335 28 : OGRLineString *poOGRLine = new OGRLineString();
336 :
337 : poOGRLine->setPoints( poLine->nVertices,
338 28 : poLine->padfX, poLine->padfY, poLine->padfZ );
339 28 : poFeature->SetGeometryDirectly( poOGRLine );
340 28 : poFeature->SetField( "SNID", (int) poLine->oStartNode.nRecord );
341 28 : poFeature->SetField( "ENID", (int) poLine->oEndNode.nRecord );
342 : }
343 28 : break;
344 :
345 : /* -------------------------------------------------------------------- */
346 : /* Translate polygon feature specific information and geometry. */
347 : /* -------------------------------------------------------------------- */
348 : case SLTPoly:
349 : {
350 36 : SDTSRawPolygon *poPoly = (SDTSRawPolygon *) poSDTSFeature;
351 36 : OGRPolygon *poOGRPoly = new OGRPolygon();
352 :
353 54 : for( int iRing = 0; iRing < poPoly->nRings; iRing++ )
354 : {
355 18 : OGRLinearRing *poRing = new OGRLinearRing();
356 : int nVertices;
357 :
358 18 : if( iRing == poPoly->nRings - 1 )
359 14 : nVertices = poPoly->nVertices - poPoly->panRingStart[iRing];
360 : else
361 4 : nVertices = poPoly->panRingStart[iRing+1]
362 4 : - poPoly->panRingStart[iRing];
363 :
364 : poRing->setPoints( nVertices,
365 18 : poPoly->padfX + poPoly->panRingStart[iRing],
366 18 : poPoly->padfY + poPoly->panRingStart[iRing],
367 54 : poPoly->padfZ + poPoly->panRingStart[iRing] );
368 :
369 18 : poOGRPoly->addRingDirectly( poRing );
370 : }
371 :
372 36 : 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 388 : for( iAttrRecord = 0;
386 : iAttrRecord < poSDTSFeature->nAttributes;
387 : iAttrRecord++)
388 : {
389 : DDFField *poSR;
390 :
391 6 : poSR = poTransfer->GetAttr( poSDTSFeature->paoATID+iAttrRecord );
392 :
393 6 : AssignAttrRecordToFeature( poFeature, poTransfer, poSR );
394 : }
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* If this record is an attribute record, attach the local */
398 : /* attributes. */
399 : /* -------------------------------------------------------------------- */
400 382 : if( poTransfer->GetLayerType(iLayer) == SLTAttr )
401 : {
402 : AssignAttrRecordToFeature( poFeature, poTransfer,
403 189 : ((SDTSAttrRecord *) poSDTSFeature)->poATTR);
404 : }
405 :
406 : /* -------------------------------------------------------------------- */
407 : /* Translate the record id. */
408 : /* -------------------------------------------------------------------- */
409 382 : poFeature->SetFID( poSDTSFeature->oModId.nRecord );
410 382 : poFeature->SetField( 0, (int) poSDTSFeature->oModId.nRecord );
411 382 : if( poFeature->GetGeometryRef() != NULL )
412 : poFeature->GetGeometryRef()->assignSpatialReference(
413 193 : poDS->GetSpatialRef() );
414 :
415 382 : if( !poReader->IsIndexed() )
416 346 : delete poSDTSFeature;
417 :
418 382 : return poFeature;
419 : }
420 :
421 :
422 : /************************************************************************/
423 : /* GetNextFeature() */
424 : /************************************************************************/
425 :
426 390 : OGRFeature *OGRSDTSLayer::GetNextFeature()
427 :
428 : {
429 390 : 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 390 : poFeature = GetNextUnfilteredFeature();
438 390 : if( poFeature == NULL )
439 8 : break;
440 :
441 382 : if( (m_poFilterGeom == NULL
442 : || FilterGeometry( poFeature->GetGeometryRef() ) )
443 : && (m_poAttrQuery == NULL
444 : || m_poAttrQuery->Evaluate( poFeature )) )
445 382 : break;
446 :
447 0 : delete poFeature;
448 : }
449 :
450 390 : 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 : }
|