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