1 /* ****************************************************************************
2 *
3 * Project: SDTS Translator
4 * Purpose: Mainline for converting to ArcView Shapefiles.
5 * Author: Frank Warmerdam, warmerdam@pobox.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1999, Frank Warmerdam
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "sdts_al.h"
30 #include "shapefil.h"
31 #include "cpl_string.h"
32
33 CPL_CVSID("$Id: sdts2shp.cpp 33cf0e31a992be112b3091f012368d15605ed51d 2021-03-16 17:51:59 -0500 ben $")
34
35 static int bVerbose = FALSE;
36
37 static void WriteLineShapefile( const char *, SDTSTransfer *,
38 const char * );
39 static void WritePointShapefile( const char *, SDTSTransfer *,
40 const char * );
41 static void WriteAttributeDBF( const char *, SDTSTransfer *,
42 const char * );
43 static void WritePolygonShapefile( const char *, SDTSTransfer *,
44 const char * );
45
46 static void
47 AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer * poTransfer,
48 char ** papszModuleList );
49 static void
50 WritePrimaryAttrToDBF( DBFHandle hDBF, int nRecord,
51 SDTSTransfer *, SDTSFeature * poFeature );
52 static void
53 WriteAttrRecordToDBF( DBFHandle hDBF, int nRecord,
54 SDTSTransfer *, DDFField * poAttributes );
55
56 /* **********************************************************************/
57 /* Usage() */
58 /* **********************************************************************/
59
Usage()60 static void Usage()
61
62 {
63 printf( "Usage: sdts2shp CATD_filename [-o shapefile_name]\n" /*ok*/
64 " [-m module_name] [-v]\n"
65 "\n"
66 "Modules include `LE01', `PC01', `NP01' and `ARDF'\n" );
67
68 exit( 1 );
69 }
70
71 /* **********************************************************************/
72 /* main() */
73 /* **********************************************************************/
74
main(int nArgc,char ** papszArgv)75 int main( int nArgc, char ** papszArgv )
76
77 {
78 {
79 int i;
80 const char *pszCATDFilename = NULL;
81 const char *pszMODN = "LE01";
82 char *pszShapefile = "sdts_out.shp";
83 SDTSTransfer oTransfer;
84
85 /* -------------------------------------------------------------------- */
86 /* Interpret commandline switches. */
87 /* -------------------------------------------------------------------- */
88 if( nArgc < 2 )
89 Usage();
90
91 pszCATDFilename = papszArgv[1];
92
93 for( i = 2; i < nArgc; i++ )
94 {
95 if( EQUAL(papszArgv[i],"-m") && i+1 < nArgc )
96 pszMODN = papszArgv[++i];
97 else if( EQUAL(papszArgv[i],"-o") && i+1 < nArgc )
98 pszShapefile = papszArgv[++i];
99 else if( EQUAL(papszArgv[i],"-v") )
100 bVerbose = TRUE;
101 else
102 {
103 printf( "Incomplete, or unsupported option `%s'\n\n",/*ok*/
104 papszArgv[i] );
105 Usage();
106 }
107 }
108
109 /* -------------------------------------------------------------------- */
110 /* Massage shapefile name to have no extension. */
111 /* -------------------------------------------------------------------- */
112 pszShapefile = CPLStrdup(pszShapefile);
113 for( i = strlen(pszShapefile)-1; i >= 0; i-- )
114 {
115 if( pszShapefile[i] == '.' )
116 {
117 pszShapefile[i] = '\0';
118 break;
119 }
120 else if( pszShapefile[i] == '/' || pszShapefile[i] == '\\' )
121 break;
122 }
123
124 /* -------------------------------------------------------------------- */
125 /* Open the transfer. */
126 /* -------------------------------------------------------------------- */
127 if( !oTransfer.Open( pszCATDFilename ) )
128 {
129 fprintf( stderr,
130 "Failed to read CATD file `%s'\n",
131 pszCATDFilename );
132 exit( 100 );
133 }
134
135 /* -------------------------------------------------------------------- */
136 /* Dump available layer in verbose mode. */
137 /* -------------------------------------------------------------------- */
138 if( bVerbose )
139 {
140 printf( "Layers:\n" );/*ok*/
141 for( i = 0; i < oTransfer.GetLayerCount(); i++ )
142 {
143 int iCATDEntry = oTransfer.GetLayerCATDEntry(i);
144
145 printf( " %s: `%s'\n",/*ok*/
146 oTransfer.GetCATD()->GetEntryModule(iCATDEntry),
147 oTransfer.GetCATD()->GetEntryTypeDesc(iCATDEntry) );
148 }
149 printf( "\n" );/*ok*/
150 }
151
152 /* -------------------------------------------------------------------- */
153 /* Check that module exists. */
154 /* -------------------------------------------------------------------- */
155 if( oTransfer.FindLayer( pszMODN ) == -1 )
156 {
157 fprintf( stderr, "Unable to identify module: %s\n", pszMODN );
158 exit( 1 );
159 }
160
161 /* -------------------------------------------------------------------- */
162 /* If the module is an LE module, write it to an Arc file. */
163 /* -------------------------------------------------------------------- */
164 if( pszMODN[0] == 'L' || pszMODN[0] == 'l' )
165 {
166 WriteLineShapefile( pszShapefile, &oTransfer, pszMODN );
167 }
168
169 /* -------------------------------------------------------------------- */
170 /* If the module is an attribute primary one, dump to DBF. */
171 /* -------------------------------------------------------------------- */
172 else if( pszMODN[0] == 'A' || pszMODN[0] == 'a'
173 || pszMODN[0] == 'B' || pszMODN[0] == 'b' )
174 {
175 WriteAttributeDBF( pszShapefile, &oTransfer, pszMODN );
176 }
177
178 /* -------------------------------------------------------------------- */
179 /* If the module is a point one, dump to Shapefile. */
180 /* -------------------------------------------------------------------- */
181 else if( pszMODN[0] == 'N' || pszMODN[0] == 'n' )
182 {
183 WritePointShapefile( pszShapefile, &oTransfer, pszMODN );
184 }
185
186 /* -------------------------------------------------------------------- */
187 /* If the module is a polygon one, dump to Shapefile. */
188 /* -------------------------------------------------------------------- */
189 else if( pszMODN[0] == 'P' || pszMODN[0] == 'p' )
190 {
191 WritePolygonShapefile( pszShapefile, &oTransfer, pszMODN );
192 }
193
194 else
195 {
196 fprintf( stderr, "Unrecognized module name: %s\n", pszMODN );
197 }
198
199 CPLFree( pszShapefile );
200 }
201 #ifdef DBMALLOC
202 malloc_dump(1);
203 #endif
204 }
205
206 /* **********************************************************************/
207 /* WriteLineShapefile() */
208 /* **********************************************************************/
209
WriteLineShapefile(const char * pszShapefile,SDTSTransfer * poTransfer,const char * pszMODN)210 static void WriteLineShapefile( const char * pszShapefile,
211 SDTSTransfer * poTransfer,
212 const char * pszMODN )
213
214 {
215 /* -------------------------------------------------------------------- */
216 /* Fetch a reference to the indexed Pointgon reader. */
217 /* -------------------------------------------------------------------- */
218 SDTSLineReader *poLineReader = (SDTSLineReader *)
219 poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
220
221 if( poLineReader == NULL )
222 {
223 fprintf( stderr, "Failed to open %s.\n",
224 poTransfer->GetCATD()->GetModuleFilePath( pszMODN ) );
225 return;
226 }
227
228 poLineReader->Rewind();
229
230 /* -------------------------------------------------------------------- */
231 /* Create the Shapefile. */
232 /* -------------------------------------------------------------------- */
233 SHPHandle hSHP;
234
235 hSHP = SHPCreate( pszShapefile, SHPT_ARC );
236 if( hSHP == NULL )
237 {
238 fprintf( stderr, "Unable to create shapefile `%s'\n",
239 pszShapefile );
240 return;
241 }
242
243 /* -------------------------------------------------------------------- */
244 /* Create the database file, and our basic set of attributes. */
245 /* -------------------------------------------------------------------- */
246 DBFHandle hDBF;
247 int nLeftPolyField, nRightPolyField;
248 int nStartNodeField, nEndNodeField, nSDTSRecordField;
249 char szDBFFilename[1024];
250
251 sprintf( szDBFFilename, "%s.dbf", pszShapefile );
252
253 hDBF = DBFCreate( szDBFFilename );
254 if( hDBF == NULL )
255 {
256 fprintf( stderr, "Unable to create shapefile .dbf for `%s'\n",
257 pszShapefile );
258 return;
259 }
260
261 nSDTSRecordField = DBFAddField( hDBF, "SDTSRecId", FTInteger, 8, 0 );
262 nLeftPolyField = DBFAddField( hDBF, "LeftPoly", FTString, 12, 0 );
263 nRightPolyField = DBFAddField( hDBF, "RightPoly", FTString, 12, 0 );
264 nStartNodeField = DBFAddField( hDBF, "StartNode", FTString, 12, 0 );
265 nEndNodeField = DBFAddField( hDBF, "EndNode", FTString, 12, 0 );
266
267 char **papszModRefs = poLineReader->ScanModuleReferences();
268 AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszModRefs );
269 CSLDestroy( papszModRefs );
270
271 /* ==================================================================== */
272 /* Process all the line features in the module. */
273 /* ==================================================================== */
274 SDTSRawLine *poRawLine = NULL;
275
276 while( (poRawLine = poLineReader->GetNextLine()) != NULL )
277 {
278 /* -------------------------------------------------------------------- */
279 /* Write out a shape with the vertices. */
280 /* -------------------------------------------------------------------- */
281 SHPObject *psShape =
282 SHPCreateSimpleObject( SHPT_ARC, poRawLine->nVertices,
283 poRawLine->padfX, poRawLine->padfY,
284 poRawLine->padfZ );
285
286 int iShape = SHPWriteObject( hSHP, -1, psShape );
287
288 SHPDestroyObject( psShape );
289
290 /* -------------------------------------------------------------------- */
291 /* Write out the attributes. */
292 /* -------------------------------------------------------------------- */
293 char szID[13];
294
295 DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
296 poRawLine->oModId.nRecord );
297
298 sprintf( szID, "%s:%d",
299 poRawLine->oLeftPoly.szModule,
300 poRawLine->oLeftPoly.nRecord );
301 DBFWriteStringAttribute( hDBF, iShape, nLeftPolyField, szID );
302
303 sprintf( szID, "%s:%d",
304 poRawLine->oRightPoly.szModule,
305 poRawLine->oRightPoly.nRecord );
306 DBFWriteStringAttribute( hDBF, iShape, nRightPolyField, szID );
307
308 sprintf( szID, "%s:%d",
309 poRawLine->oStartNode.szModule,
310 poRawLine->oStartNode.nRecord );
311 DBFWriteStringAttribute( hDBF, iShape, nStartNodeField, szID );
312
313 sprintf( szID, "%s:%d",
314 poRawLine->oEndNode.szModule,
315 poRawLine->oEndNode.nRecord );
316 DBFWriteStringAttribute( hDBF, iShape, nEndNodeField, szID );
317
318 WritePrimaryAttrToDBF( hDBF, iShape, poTransfer, poRawLine );
319
320 if( !poLineReader->IsIndexed() )
321 delete poRawLine;
322 }
323
324 /* -------------------------------------------------------------------- */
325 /* Close, and cleanup. */
326 /* -------------------------------------------------------------------- */
327 DBFClose( hDBF );
328 SHPClose( hSHP );
329 }
330
331 /* **********************************************************************/
332 /* WritePointShapefile() */
333 /* **********************************************************************/
334
WritePointShapefile(const char * pszShapefile,SDTSTransfer * poTransfer,const char * pszMODN)335 static void WritePointShapefile( const char * pszShapefile,
336 SDTSTransfer * poTransfer,
337 const char * pszMODN )
338
339 {
340 /* -------------------------------------------------------------------- */
341 /* Fetch a reference to the indexed Pointgon reader. */
342 /* -------------------------------------------------------------------- */
343 SDTSPointReader *poPointReader = (SDTSPointReader *)
344 poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
345
346 if( poPointReader == NULL )
347 {
348 fprintf( stderr, "Failed to open %s.\n",
349 poTransfer->GetCATD()->GetModuleFilePath( pszMODN ) );
350 return;
351 }
352
353 poPointReader->Rewind();
354
355 /* -------------------------------------------------------------------- */
356 /* Create the Shapefile. */
357 /* -------------------------------------------------------------------- */
358 SHPHandle hSHP;
359
360 hSHP = SHPCreate( pszShapefile, SHPT_POINT );
361 if( hSHP == NULL )
362 {
363 fprintf( stderr, "Unable to create shapefile `%s'\n",
364 pszShapefile );
365 return;
366 }
367
368 /* -------------------------------------------------------------------- */
369 /* Create the database file, and our basic set of attributes. */
370 /* -------------------------------------------------------------------- */
371 DBFHandle hDBF;
372 int nAreaField, nSDTSRecordField;
373 char szDBFFilename[1024];
374
375 sprintf( szDBFFilename, "%s.dbf", pszShapefile );
376
377 hDBF = DBFCreate( szDBFFilename );
378 if( hDBF == NULL )
379 {
380 fprintf( stderr, "Unable to create shapefile .dbf for `%s'\n",
381 pszShapefile );
382 return;
383 }
384
385 nSDTSRecordField = DBFAddField( hDBF, "SDTSRecId", FTInteger, 8, 0 );
386 nAreaField = DBFAddField( hDBF, "AreaId", FTString, 12, 0 );
387
388 char **papszModRefs = poPointReader->ScanModuleReferences();
389 AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszModRefs );
390 CSLDestroy( papszModRefs );
391
392 /* ==================================================================== */
393 /* Process all the line features in the module. */
394 /* ==================================================================== */
395 SDTSRawPoint *poRawPoint = NULL;
396
397 while( (poRawPoint = poPointReader->GetNextPoint()) != NULL )
398 {
399 /* -------------------------------------------------------------------- */
400 /* Write out a shape with the vertices. */
401 /* -------------------------------------------------------------------- */
402 SHPObject *psShape =
403 SHPCreateSimpleObject( SHPT_POINT, 1,
404 &(poRawPoint->dfX),
405 &(poRawPoint->dfY),
406 &(poRawPoint->dfZ) );
407
408 int iShape = SHPWriteObject( hSHP, -1, psShape );
409
410 SHPDestroyObject( psShape );
411
412 /* -------------------------------------------------------------------- */
413 /* Write out the attributes. */
414 /* -------------------------------------------------------------------- */
415 char szID[13];
416
417 DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
418 poRawPoint->oModId.nRecord );
419
420 sprintf( szID, "%s:%d",
421 poRawPoint->oAreaId.szModule,
422 poRawPoint->oAreaId.nRecord );
423 DBFWriteStringAttribute( hDBF, iShape, nAreaField, szID );
424
425 WritePrimaryAttrToDBF( hDBF, iShape, poTransfer, poRawPoint );
426
427 if( !poPointReader->IsIndexed() )
428 delete poRawPoint;
429 }
430
431 /* -------------------------------------------------------------------- */
432 /* Close, and cleanup. */
433 /* -------------------------------------------------------------------- */
434 DBFClose( hDBF );
435 SHPClose( hSHP );
436 }
437
438 /* **********************************************************************/
439 /* WriteAttributeDBF() */
440 /* **********************************************************************/
441
WriteAttributeDBF(const char * pszShapefile,SDTSTransfer * poTransfer,const char * pszMODN)442 static void WriteAttributeDBF( const char * pszShapefile,
443 SDTSTransfer * poTransfer,
444 const char * pszMODN )
445
446 {
447 /* -------------------------------------------------------------------- */
448 /* Fetch a reference to the indexed Pointgon reader. */
449 /* -------------------------------------------------------------------- */
450 SDTSAttrReader *poAttrReader = (SDTSAttrReader *)
451 poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
452
453 if( poAttrReader == NULL )
454 {
455 fprintf( stderr, "Failed to open %s.\n",
456 poTransfer->GetCATD()->GetModuleFilePath( pszMODN ) );
457 return;
458 }
459
460 poAttrReader->Rewind();
461
462 /* -------------------------------------------------------------------- */
463 /* Create the database file, and our basic set of attributes. */
464 /* -------------------------------------------------------------------- */
465 DBFHandle hDBF;
466 char szDBFFilename[1024];
467
468 sprintf( szDBFFilename, "%s.dbf", pszShapefile );
469
470 hDBF = DBFCreate( szDBFFilename );
471 if( hDBF == NULL )
472 {
473 fprintf( stderr, "Unable to create shapefile .dbf for `%s'\n",
474 pszShapefile );
475 return;
476 }
477
478 DBFAddField( hDBF, "SDTSRecId", FTInteger, 8, 0 );
479
480 /* -------------------------------------------------------------------- */
481 /* Prepare the schema. */
482 /* -------------------------------------------------------------------- */
483 char **papszMODNList = CSLAddString( NULL, pszMODN );
484
485 AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszMODNList );
486
487 CSLDestroy( papszMODNList );
488
489 /* ==================================================================== */
490 /* Process all the records in the module. */
491 /* ==================================================================== */
492 SDTSAttrRecord *poRecord = NULL;
493 int iRecord = 0;
494
495 while( (poRecord = (SDTSAttrRecord*)poAttrReader->GetNextFeature())
496 != NULL )
497 {
498 DBFWriteIntegerAttribute( hDBF, iRecord, 0,
499 poRecord->oModId.nRecord );
500
501 WriteAttrRecordToDBF( hDBF, iRecord, poTransfer, poRecord->poATTR );
502
503 if( !poAttrReader->IsIndexed() )
504 delete poRecord;
505
506 iRecord++;
507 }
508
509 /* -------------------------------------------------------------------- */
510 /* Close, and cleanup. */
511 /* -------------------------------------------------------------------- */
512 DBFClose( hDBF );
513 }
514
515 /* **********************************************************************/
516 /* WritePolygonShapefile() */
517 /* **********************************************************************/
518
WritePolygonShapefile(const char * pszShapefile,SDTSTransfer * poTransfer,const char * pszMODN)519 static void WritePolygonShapefile( const char * pszShapefile,
520 SDTSTransfer * poTransfer,
521 const char * pszMODN )
522
523 {
524 /* -------------------------------------------------------------------- */
525 /* Fetch a reference to the indexed polygon reader. */
526 /* -------------------------------------------------------------------- */
527 SDTSPolygonReader *poPolyReader = (SDTSPolygonReader *)
528 poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
529
530 if( poPolyReader == NULL )
531 {
532 fprintf( stderr, "Failed to open %s.\n",
533 poTransfer->GetCATD()->GetModuleFilePath( pszMODN ) );
534 return;
535 }
536
537 /* -------------------------------------------------------------------- */
538 /* Assemble polygon geometries from all the line layers. */
539 /* -------------------------------------------------------------------- */
540 poPolyReader->AssembleRings( poTransfer, poTransfer->FindLayer(pszMODN) );
541
542 /* -------------------------------------------------------------------- */
543 /* Create the Shapefile. */
544 /* -------------------------------------------------------------------- */
545 SHPHandle hSHP;
546
547 hSHP = SHPCreate( pszShapefile, SHPT_POLYGON );
548 if( hSHP == NULL )
549 {
550 fprintf( stderr, "Unable to create shapefile `%s'\n",
551 pszShapefile );
552 return;
553 }
554
555 /* -------------------------------------------------------------------- */
556 /* Create the database file, and our basic set of attributes. */
557 /* -------------------------------------------------------------------- */
558 DBFHandle hDBF;
559 int nSDTSRecordField;
560 char szDBFFilename[1024];
561
562 sprintf( szDBFFilename, "%s.dbf", pszShapefile );
563
564 hDBF = DBFCreate( szDBFFilename );
565 if( hDBF == NULL )
566 {
567 fprintf( stderr, "Unable to create shapefile .dbf for `%s'\n",
568 pszShapefile );
569 return;
570 }
571
572 nSDTSRecordField = DBFAddField( hDBF, "SDTSRecId", FTInteger, 8, 0 );
573
574 char **papszModRefs = poPolyReader->ScanModuleReferences();
575 AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszModRefs );
576 CSLDestroy( papszModRefs );
577
578 /* ==================================================================== */
579 /* Process all the polygon features in the module. */
580 /* ==================================================================== */
581 poPolyReader->Rewind();
582
583 SDTSRawPolygon *poRawPoly = NULL;
584 while( (poRawPoly = (SDTSRawPolygon *) poPolyReader->GetNextFeature())
585 != NULL )
586 {
587 /* -------------------------------------------------------------------- */
588 /* Write out a shape with the vertices. */
589 /* -------------------------------------------------------------------- */
590 SHPObject *psShape =
591 SHPCreateObject( SHPT_POLYGON, -1, poRawPoly->nRings,
592 poRawPoly->panRingStart, NULL,
593 poRawPoly->nVertices,
594 poRawPoly->padfX,
595 poRawPoly->padfY,
596 poRawPoly->padfZ,
597 NULL );
598
599 int iShape = SHPWriteObject( hSHP, -1, psShape );
600
601 SHPDestroyObject( psShape );
602
603 /* -------------------------------------------------------------------- */
604 /* Write out the attributes. */
605 /* -------------------------------------------------------------------- */
606 DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
607 poRawPoly->oModId.nRecord );
608 WritePrimaryAttrToDBF( hDBF, iShape, poTransfer, poRawPoly );
609
610 if( !poPolyReader->IsIndexed() )
611 delete poRawPoly;
612 }
613
614 /* -------------------------------------------------------------------- */
615 /* Close, and cleanup. */
616 /* -------------------------------------------------------------------- */
617 DBFClose( hDBF );
618 SHPClose( hSHP );
619 }
620
621 /* **********************************************************************/
622 /* AddPrimaryAttrToDBF() */
623 /* */
624 /* Add the fields from all the given primary attribute modules */
625 /* to the schema of the passed DBF file. */
626 /* **********************************************************************/
627
628 static void
AddPrimaryAttrToDBFSchema(DBFHandle hDBF,SDTSTransfer * poTransfer,char ** papszModuleList)629 AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
630 char ** papszModuleList )
631
632 {
633 for( int iModule = 0;
634 papszModuleList != NULL && papszModuleList[iModule] != NULL;
635 iModule++ )
636 {
637 /* -------------------------------------------------------------------- */
638 /* Get a reader on the desired module. */
639 /* -------------------------------------------------------------------- */
640 SDTSAttrReader *poAttrReader = (SDTSAttrReader *)
641 poTransfer->GetLayerIndexedReader(
642 poTransfer->FindLayer( papszModuleList[iModule] ) );
643
644 if( poAttrReader == NULL )
645 {
646 printf( "Unable to open attribute module %s, skipping.\n" ,/*ok*/
647 papszModuleList[iModule] );
648 continue;
649 }
650
651 poAttrReader->Rewind();
652
653 /* -------------------------------------------------------------------- */
654 /* Read the first record so we can clone schema information off */
655 /* of it. */
656 /* -------------------------------------------------------------------- */
657 SDTSAttrRecord *poAttrFeature =
658 (SDTSAttrRecord *) poAttrReader->GetNextFeature();
659 if( poAttrFeature == NULL )
660 {
661 fprintf( stderr,
662 "Didn't find any meaningful attribute records in %s.\n",
663 papszModuleList[iModule] );
664
665 continue;
666 }
667
668 /* -------------------------------------------------------------------- */
669 /* Clone schema off the first record. Eventually we need to */
670 /* get the information out of the DDR record, but it isn't */
671 /* clear to me how to accomplish that with the SDTS++ API. */
672 /* */
673 /* The following approach may fail (dramatically) if some */
674 /* records do not include all subfields. Furthermore, no */
675 /* effort is made to make DBF field names unique. The SDTS */
676 /* attributes often have names much beyond the 14 character dbf */
677 /* limit which may result in non-unique attributes. */
678 /* -------------------------------------------------------------------- */
679 DDFFieldDefn *poFDefn = poAttrFeature->poATTR->GetFieldDefn();
680 int iSF;
681 DDFField *poSR = poAttrFeature->poATTR;
682
683 for( iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
684 {
685 DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
686 int nWidth = poSFDefn->GetWidth();
687
688 switch( poSFDefn->GetType() )
689 {
690 case DDFString:
691 if( nWidth == 0 )
692 {
693 int nMaxBytes;
694
695 const char * pachData = poSR->GetSubfieldData(poSFDefn,
696 &nMaxBytes);
697
698 nWidth = strlen(poSFDefn->ExtractStringData(pachData,
699 nMaxBytes, NULL ));
700 }
701
702 DBFAddField( hDBF, poSFDefn->GetName(), FTString, nWidth, 0 );
703 break;
704
705 case DDFInt:
706 if( nWidth == 0 )
707 nWidth = 9;
708
709 DBFAddField( hDBF, poSFDefn->GetName(), FTInteger, nWidth, 0 );
710 break;
711
712 case DDFFloat:
713 DBFAddField( hDBF, poSFDefn->GetName(), FTDouble, 18, 6 );
714 break;
715
716 default:
717 fprintf( stderr,
718 "Dropping attribute `%s' of module `%s'. "
719 "Type unsupported\n",
720 poSFDefn->GetName(),
721 papszModuleList[iModule] );
722 break;
723 }
724 }
725
726 if( !poAttrReader->IsIndexed() )
727 delete poAttrFeature;
728 } /* next module */
729 }
730
731 /* **********************************************************************/
732 /* WritePrimaryAttrToDBF() */
733 /* **********************************************************************/
734
735 static void
WritePrimaryAttrToDBF(DBFHandle hDBF,int iRecord,SDTSTransfer * poTransfer,SDTSFeature * poFeature)736 WritePrimaryAttrToDBF( DBFHandle hDBF, int iRecord,
737 SDTSTransfer * poTransfer, SDTSFeature * poFeature )
738
739 {
740 /* ==================================================================== */
741 /* Loop over all the attribute records linked to this feature. */
742 /* ==================================================================== */
743 for( int iAttrRecord = 0;
744 iAttrRecord < poFeature->nAttributes;
745 iAttrRecord++ )
746 {
747 DDFField *poSR = poTransfer->GetAttr( poFeature->paoATID+iAttrRecord );
748
749 WriteAttrRecordToDBF( hDBF, iRecord, poTransfer, poSR );
750 }
751 }
752
753 /* **********************************************************************/
754 /* WriteAttrRecordToDBF() */
755 /* **********************************************************************/
756
757 static void
WriteAttrRecordToDBF(DBFHandle hDBF,int iRecord,SDTSTransfer * poTransfer,DDFField * poSR)758 WriteAttrRecordToDBF( DBFHandle hDBF, int iRecord,
759 SDTSTransfer * poTransfer, DDFField * poSR )
760
761 {
762 /* -------------------------------------------------------------------- */
763 /* Process each subfield in the record. */
764 /* -------------------------------------------------------------------- */
765 DDFFieldDefn *poFDefn = poSR->GetFieldDefn();
766
767 for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
768 {
769 DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
770 int iField;
771 int nMaxBytes;
772 const char * pachData = poSR->GetSubfieldData(poSFDefn,
773 &nMaxBytes);
774
775 /* -------------------------------------------------------------------- */
776 /* Identify the related DBF field, if any. */
777 /* -------------------------------------------------------------------- */
778 for( iField = 0; iField < hDBF->nFields; iField++ )
779 {
780 if( EQUALN(poSFDefn->GetName(),
781 hDBF->pszHeader+iField*32,10) )
782 break;
783 }
784
785 if( iField == hDBF->nFields )
786 iField = -1;
787
788 /* -------------------------------------------------------------------- */
789 /* Handle each of the types. */
790 /* -------------------------------------------------------------------- */
791 switch (poSFDefn->GetType())
792 {
793 case DDFString:
794 {
795 const char *pszValue = poSFDefn->ExtractStringData(pachData, nMaxBytes, NULL);
796
797 if (iField != -1)
798 DBFWriteStringAttribute(hDBF, iRecord, iField, pszValue);
799 }
800 break;
801
802 case DDFFloat:
803 {
804 double dfValue;
805
806 dfValue = poSFDefn->ExtractFloatData(pachData, nMaxBytes,
807 NULL);
808
809 if (iField != -1)
810 DBFWriteDoubleAttribute(hDBF, iRecord, iField, dfValue);
811 }
812 break;
813
814 case DDFInt:
815 {
816 int nValue;
817
818 nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL);
819
820 if (iField != -1)
821 DBFWriteIntegerAttribute(hDBF, iRecord, iField, nValue);
822 }
823 break;
824 default:
825 break;
826 }
827 } /* next subfield */
828 }
829