1
/************************************************************************************
2
TerraLib - a library for developing GIS applications.
3
Copyright ļæ½ 2001-2004 INPE and Tecgraf/PUC-Rio.
5
This code is part of the TerraLib library.
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2.1 of the License, or (at your option) any later version.
11
You should have received a copy of the GNU Lesser General Public
12
License along with this library.
14
The authors reassure the license terms regarding the warranties.
15
They specifically disclaim any warranties, including, but not limited to,
16
the implied warranties of merchantability and fitness for a particular purpose.
17
The library provided hereunder is on an "as is" basis, and the authors have no
18
obligation to provide maintenance, support, updates, enhancements, or modifications.
19
In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
20
indirect, special, incidental, or consequential damages arising out of the use
21
of this library and its documentation.
22
*************************************************************************************/
36
#include "TeImportExport.h"
38
#include "TeGeometry.h"
39
#include "TeAsciiFile.h"
40
#include "TeMIFProjection.h"
41
#include "TeException.h"
42
#include "TeProjection.h"
43
#include "TeAttribute.h"
45
#include "TeAssertions.h"
48
#include "TeGeometryAlgorithms.h"
49
#include "TeDatabase.h"
51
void TeMIFRegionDecode ( TeAsciiFile& mifFile, TePolygonSet& temp, string& index);
53
void TeMIFLineDecode (TeAsciiFile& mifFile, TeLineSet& temp, string& index);
55
void TeMIFPlineDecode (TeAsciiFile& mifFile, TeLineSet& temp, string& index);
57
void TeMIFPointDecode (TeAsciiFile& mifFile, TePointSet& temp, string& index);
59
void TeMIFMultiPointDecode (TeAsciiFile& mifFile, TePointSet& temp, string& index);
61
void TeMIFTextDecode (TeAsciiFile& mifFile, TeTextSet& temp, string& index);
63
void TeMIFCollectionDecode(TeAsciiFile& mifFile, TePointSet& ps, TeLineSet& ls, TePolygonSet& pols, string& index);
65
void TeMIFRectDecode (TeAsciiFile& mifFile, TePolygonSet& temp, string& index);
67
void TeMIFOthersDecode ( TeAsciiFile& );
69
void TeMIFTransformDecode ( TeAsciiFile& );
71
bool TeReadMIFAttributes(TeAsciiFile& midFile, TeTable& attTable,
72
int ncolumns, int nrecords=-1, int delta = 0, bool createAuto=false);
74
bool TeImportMIFGeometries(TeLayer* layer,const string& mifFileName,
75
vector<string> &indexes, unsigned int chunckSize);
77
char TeReadMIFSeparator(const string& mifFileName);
79
double glXmulti = 1., glYmulti = 1;
81
TeCoord2D glAdd (0., 0. );
84
TeLayer* TeImportMIF(const string& mifFileName, TeDatabase* db, const string& layerName)
86
if (!db || mifFileName.empty())
89
// check if format is complete (MID and MIF files exist)
90
string filePrefix = TeGetName(mifFileName.c_str());
91
string ftest = filePrefix + ".mid";
92
if (access(ftest.c_str(),04) == -1)
94
ftest = filePrefix + ".MID";
95
if (access(ftest.c_str(),04) == -1)
99
ftest = filePrefix + ".mif";
100
if (access(ftest.c_str(),04) == -1)
102
ftest = filePrefix + ".MIF";
103
if (access(ftest.c_str(),04) == -1)
107
// found a valid layer name
109
string baseName = TeGetBaseName(mifFileName.c_str());
110
if (layerName.empty())
115
string newLayerName = lName;
116
TeLayerMap& layerMap = db->layerMap();
117
TeLayerMap::iterator it;
122
for (it = layerMap.begin(); it != layerMap.end(); ++it)
124
if (TeStringCompare(it->second->name(),newLayerName))
127
if (it == layerMap.end())
130
newLayerName = lName + "_" +Te2String(n);
135
TeProjection* mifProj = TeReadMIFProjection(mifFileName);
136
TeLayer* newLayer = new TeLayer(newLayerName,db,mifProj);
137
if (newLayer->id() <= 0 )
138
return 0; // couldnļæ½t create new layer
140
bool res = TeImportMIF(newLayer,mifFileName);
146
db->deleteLayer(newLayer->id());
153
TeImportMIF(TeLayer* layer, const string& mifFileName, string attrTableName,
154
string objectIdAttr, unsigned int chunkSize)
156
// check if format is complete (MID and MIF files exist)
157
string filePrefix = TeGetName(mifFileName.c_str());
158
string ftest = filePrefix + ".mid";
159
if (access(ftest.c_str(),04) == -1)
161
ftest = filePrefix + ".MID";
162
if (access(ftest.c_str(),04) == -1)
166
ftest = filePrefix + ".mif";
167
if (access(ftest.c_str(),04) == -1)
169
ftest = filePrefix + ".MIF";
170
if (access(ftest.c_str(),04) == -1)
175
//-- Step 1: Read any adicional information (ex. projection)
176
if (!layer->projection())
178
TeProjection* mifProj = TeReadMIFProjection(mifFileName);
180
layer->setProjection(mifProj);
183
char separator = TeReadMIFSeparator(mifFileName);
185
//read the attribute list information
186
TeAttributeList attList;
187
TeReadMIFAttributeList(mifFileName, attList);
189
// define a TeAttributeTable
190
if (attrTableName.empty())
192
if (layer->name().empty())
195
attrTableName = layer->name();
197
string aux = attrTableName;
199
while (layer->database()->tableExist(aux))
201
aux = attrTableName + "_" + Te2String(c);
207
bool autoIndex = false;
209
// if no geometry link name is given, creates one called 'object_id'
210
if (objectIdAttr.empty())
212
objectIdAttr = "object_id_"+Te2String(layer->id());
214
at.rep_.type_ = TeSTRING;
215
at.rep_.numChar_ = 16;
216
at.rep_.name_ = objectIdAttr;
217
at.rep_.isPrimaryKey_ = true;
218
attList.push_back(at);
223
// check if given index is valid
224
TeAttributeList::iterator it = attList.begin();
225
while (it != attList.end())
227
if (TeConvertToUpperCase((*it).rep_.name_) == TeConvertToUpperCase(objectIdAttr)) // index found
229
if ((*it).rep_.type_ != TeSTRING) // make sure it is a String type
231
(*it).rep_.type_ = TeSTRING;
232
(*it).rep_.numChar_ = 16;
235
(*it).rep_.isPrimaryKey_ = true;
241
if (it == attList.end()) // index not found
244
at.rep_.type_ = TeSTRING;
245
at.rep_.numChar_ = 16;
246
at.rep_.name_ = objectIdAttr;
247
at.rep_.isPrimaryKey_ = true;
248
attList.push_back(at);
254
linkCol = attList.size()-1;
256
TeTable attTable (attrTableName,attList,objectIdAttr,objectIdAttr,TeAttrStatic);
257
attTable.setSeparator(separator);
259
// insert the table into the database
260
if (!layer->createAttributeTable(attTable))
263
vector<string> objectIds;
265
string midFileName = filePrefix + ".mid";
267
int ncol = attList.size();
271
TeAsciiFile midFile(midFileName);
273
while (TeReadMIFAttributes(midFile,attTable,ncol,chunkSize,delta, autoIndex))
275
for (unsigned int n=0; n<attTable.size();++n)
276
objectIds.push_back(attTable.operator ()(n,linkCol));
279
if (!layer->saveAttributeTable( attTable ))
284
delta += attTable.size();
288
// Import the geometries
289
bool res = TeImportMIFGeometries(layer,mifFileName,objectIds,chunkSize);
293
bool TeReadMIFAttributes(TeAsciiFile& midFile, TeTable& attTable,
294
int ncolumns, int nrecords, int delta, bool createAuto )
296
if (!midFile.isNotAtEOF() || nrecords <=0 || ncolumns <= 0)
298
char separator = attTable.separator();
301
for (count=0; count<nrecords; count++)
303
if (!midFile.isNotAtEOF())
307
for (int n=0; n<ncolumns; n++)
312
value = midFile.readStringCSVNoQuote(separator);
321
row.push_back ( value );
325
row.push_back(Te2String(count+delta));
328
midFile.findNewLine();
334
TeReadMIFSeparator(const string& mifFileName)
336
string filePrefix = TeGetName (mifFileName.c_str()) ;
337
string fileName = filePrefix + ".mif";
339
TeAsciiFile mifFile(fileName);
340
string name = mifFile.readString ();
342
while ( mifFile.isNotAtEOF() && !TeStringCompare(name,"Delimiter"))
343
name = mifFile.readString ();
345
if (mifFile.isNotAtEOF())
346
return mifFile.readQuotedChar();
353
TeReadMIFProjection(const string& mifFileName)
355
TeProjection* proj = 0;
357
string filePrefix = TeGetName (mifFileName.c_str()) ;
358
string fileName = filePrefix + ".mif";
360
TeAsciiFile mifFile(fileName);
361
string name = mifFile.readString ();
363
while ( mifFile.isNotAtEOF() && !TeStringCompare(name,"CoordSys")
364
&& !TeStringCompare(name,"Columns"))
365
name = mifFile.readString ();
367
if (mifFile.isNotAtEOF() && TeStringCompare(name,"CoordSys"))
369
string option = mifFile.readString();
371
vector<string> argList;
373
if (TeStringCompare(option,"Earth")) // expect Projection clause
375
string projRef = mifFile.readString ();
376
if (!TeStringCompare(projRef,"Projection"))
378
proj = new TeNoProjection();
381
mifFile.readStringListCSV(argList,',');
382
proj = TeMIFProjectionFactory::make ( argList ); // create projection from parameters
384
else if (TeStringCompare(option,"Nonearth")) // non earth
386
// look for units specification
387
while (mifFile.isNotAtEOF() && !TeStringCompare(name,"Units")
388
&& !TeStringCompare(name,"Columns"))
389
name = mifFile.readString ();
390
if (TeStringCompare(name,"Units"))
392
name = mifFile.readString();
393
proj = new TeNoProjection(name);
396
proj = new TeNoProjection(name);
399
else // no CoordSys clause specified
400
{ // it should be assumed that the data is stored in Lat Long
401
TeDatum datum = TeDatumFactory::make("Spherical");
402
proj = new TeLatLong(datum);
408
TeReadMIFAttributeList ( const string& mifFileName, TeAttributeList& attList )
410
string filePrefix = TeGetName (mifFileName.c_str()) ;
411
string fileName = filePrefix + ".mif";
413
TeAsciiFile mifFile(fileName);
414
string name = mifFile.readString ();
416
while ( mifFile.isNotAtEOF() && !TeStringCompare(name,"Columns"))
417
name = mifFile.readString ();
419
if (mifFile.isNotAtEOF())
421
int ncol = mifFile.readInt();
422
mifFile.findNewLine();
423
TeAttribute attribute;
425
for ( int i = 0; i< ncol; i++ )
427
attribute.rep_.name_ = mifFile.readString();
428
string attType = mifFile.readStringCSVNoSpace ('(');
429
if ( TeStringCompare(attType,"Integer") || TeStringCompare(attType,"Smallint")
430
|| TeStringCompare(attType,"Logical") )
432
attribute.rep_.type_ = TeINT;
434
else if (TeStringCompare(attType,"Float"))
436
attribute.rep_.type_ = TeREAL;
437
attribute.rep_.numChar_ = 20;
438
attribute.rep_.decimals_ = 1;
440
else if (TeStringCompare(attType,"Date"))
442
attribute.rep_.type_ = TeDATETIME;
443
attribute.dateTimeFormat_="YYYYMMDD";
445
else if (TeStringCompare(attType,"Decimal"))
447
attribute.rep_.type_ = TeREAL;
448
attribute.rep_.numChar_ = mifFile.readIntCSV();
449
attribute.rep_.decimals_ = mifFile.readIntCSV(')');
453
attribute.rep_.type_ = TeSTRING;
454
attribute.rep_.numChar_ = mifFile.readIntCSV(')');
456
attList.push_back ( attribute );
457
mifFile.findNewLine();
463
TeImportMIFGeometries(TeLayer* layer,const string& mifFileName,
464
vector<string> &indexes, unsigned int chunckSize)
467
string filePrefix = TeGetName (mifFileName.c_str()) ;
468
string fileName = filePrefix + ".mif";
472
TePolygonSet polySet;
474
string textTableName = layer->name() + "Texto";
478
TeAsciiFile mifFile(fileName);
480
while ( mifFile.isNotAtEOF() )
482
string name = mifFile.readString ();
483
if (TeStringCompare(name,"Region"))
485
TeMIFRegionDecode ( mifFile, polySet, indexes[n]);
487
if ( polySet.size() == chunckSize )
489
layer->addPolygons( polySet );
493
else if (TeStringCompare(name,"Pline"))
495
TeMIFPlineDecode ( mifFile, lineSet, indexes[n] );
497
if ( lineSet.size() == chunckSize )
499
layer->addLines( lineSet );
503
else if (TeStringCompare(name,"Line"))
505
TeMIFLineDecode ( mifFile, lineSet, indexes[n] );
507
if ( lineSet.size() == chunckSize )
509
layer->addLines( lineSet );
513
else if (TeStringCompare(name,"Point"))
515
TeMIFPointDecode ( mifFile, pointSet, indexes[n] );
517
if ( pointSet.size() == chunckSize )
519
layer->addPoints( pointSet );
523
else if (TeStringCompare(name,"Multipoint"))
525
TeMIFMultiPointDecode ( mifFile, pointSet, indexes[n] );
527
if ( pointSet.size() == chunckSize )
529
layer->addPoints( pointSet );
533
else if (TeStringCompare(name,"Text"))
535
TeMIFTextDecode ( mifFile, textSet,indexes[n]);
537
if ( textSet.size() == chunckSize )
539
layer->addText( textSet,textTableName );
543
else if (TeStringCompare(name,"Rect"))
545
TeMIFRectDecode(mifFile,polySet,indexes[n]);
547
if (polySet.size() == chunckSize )
549
layer->addPolygons(polySet);
553
else if (TeStringCompare(name,"Collection"))
555
TeMIFCollectionDecode(mifFile,pointSet,lineSet, polySet,indexes[n]);
557
if (lineSet.size() == chunckSize )
559
layer->addLines(lineSet);
562
if (polySet.size() == chunckSize )
564
layer->addPolygons(polySet);
567
if (pointSet.size() == chunckSize )
569
layer->addPoints(pointSet);
573
else if (TeStringCompare(name,"Transform"))
574
TeMIFTransformDecode ( mifFile );
575
else if (TeStringCompare(name,"NONE"))
578
TeMIFOthersDecode ( mifFile );
581
// save the remaining geometries
582
if (pointSet.size() > 0 )
584
layer->addPoints( pointSet );
588
if (lineSet.size() > 0 )
590
layer->addLines( lineSet );
594
if (polySet.size() > 0 )
596
layer->addPolygons( polySet );
600
if (textSet.size() > 0)
602
layer->addText( textSet,textTableName );
614
TeMIFRectDecode (TeAsciiFile& mifFile, TePolygonSet& temp, string& index)
618
TeCoord2D ll = mifFile.readCoord2D();
619
TeCoord2D ur = mifFile.readCoord2D();
621
TeBox rec(ll.x_,ll.y_,ur.x_,ur.y_);
622
TePolygon pol = polygonFromBox(rec);
628
TeMIFRegionDecode ( TeAsciiFile& mifFile, TePolygonSet& temp, string& index)
633
int npolyg = mifFile.readInt();
634
mifFile.findNewLine();
638
typedef list<TePolygon> PolyList;
640
for ( int i = 0; i < npolyg; i++ )
644
int ncoord = mifFile.readInt();
645
mifFile.findNewLine();
647
for ( int j = 0; j < ncoord; j++ )
649
pt = mifFile.readCoord2D();
650
pt.scale( glXmulti, glYmulti);
652
mifFile.findNewLine();
656
if ( line.size() <= 3 ) continue; // to avoid dangling rings
657
if ( !line.isRing() ) //close the ring
660
// throw TeException ( MIF_REGION_CLOSE );
663
TeLinearRing ring (line);
667
PolyList::iterator it = pList.begin();
669
while ( it != pList.end() )
673
TePolygon p2 = (*it);
677
ring.objectId(p2[0].objectId());
678
p2.add ( ring );// add a closed region
685
ring.objectId(index);
686
poly.add ( ring ); // add an outer region
687
poly.objectId(index);
688
pList.push_back ( poly );
692
PolyList::iterator it = pList.begin();
693
while ( it != pList.end() )
695
temp.add ( *it ); // add a polygon to a layer
701
TeMIFLineDecode (TeAsciiFile& mifFile, TeLineSet& temp, string& index)
709
for ( int i= 0; i < 2; i++ )
711
pt = mifFile.readCoord2D();
712
pt.scale( glXmulti, glYmulti);
717
line.objectId( index );
719
mifFile.findNewLine();
723
TeMIFPlineDecode (TeAsciiFile& mifFile, TeLineSet& temp, string& index)
731
// Read the Pline parameters
732
vector<string> strList;
733
mifFile.readStringList ( strList );
735
// Are we dealing with MULTIPLE sections ??
736
// If there are two parameters for the pline,
737
// the first MUST be a "Multiple" keyword
739
bool hasMultiple = false;
741
if ( strList.size() == 2 )
744
ensure (TeStringCompare(strList[0],"Multiple"));
745
numSections = atoi ( strList[1].c_str() );
748
ncoord = atoi ( strList[0].c_str());
750
mifFile.findNewLine(); // go to the next line
751
// If there is a single PLine, there is a single
752
// section ( numSections = 1 ) and will read
753
// the number of points within the loop
756
for ( int i= 0; i < numSections; i++ )
760
if ( hasMultiple == true )
762
ncoord = mifFile.readInt();
763
mifFile.findNewLine(); // go to the next line
766
for ( int j = 0; j < ncoord; j++ )
768
pt = mifFile.readCoord2D();
769
pt.scale( glXmulti, glYmulti);
771
mifFile.findNewLine();
774
line.objectId( index );
780
TeMIFPointDecode (TeAsciiFile& mifFile, TePointSet& temp, string& index)
787
// Read the coordinates
789
TeCoord2D pt = mifFile.readCoord2D();
790
pt.scale( glXmulti, glYmulti);
793
point.objectId( index );
795
// Add a point to the Point Set
799
mifFile.findNewLine();
803
TeMIFMultiPointDecode (TeAsciiFile& mifFile, TePointSet& temp, string& index)
808
int npts = mifFile.readInt();
809
mifFile.findNewLine();
810
for (int i=0; i<npts;i++)
814
TeCoord2D pt = mifFile.readCoord2D();
815
pt.scale( glXmulti, glYmulti);
818
point.objectId( index );
820
// Add a point to the Point Set
823
mifFile.findNewLine();
827
TeMIFTransformDecode ( TeAsciiFile& mifFile )
829
// read the tansformation params
831
double param = mifFile.readFloatCSV();
836
param = mifFile.readFloatCSV();
841
double x = mifFile.readFloatCSV();
843
double y = mifFile.readFloatCSV();
845
TeCoord2D pt ( x, y );
849
// Go to the next line
850
mifFile.findNewLine ();
855
TeMIFTextDecode (TeAsciiFile& mifFile, TeTextSet& temp, string& index)
857
string txt = mifFile.readQuotedString(); // read the text string
858
mifFile.findNewLine ();
859
TeBox box = mifFile.readBox(); // read the text box
861
TeCoord2D lowerLeft = box.lowerLeft();
862
TeText text(lowerLeft,txt);
864
text.objectId(index);
865
text.setHeight(box.height());
867
mifFile.findNewLine (); // go to the next line
871
TeMIFOthersDecode ( TeAsciiFile& mifFile )
873
// Simply go to the next line
874
mifFile.findNewLine ();
878
TeMIFCollectionDecode(TeAsciiFile& mifFile, TePointSet& ps, TeLineSet& ls, TePolygonSet& pols, string& index)
880
int nparts = mifFile.readInt();
883
mifFile.findNewLine();
884
for (int i=0; i<nparts; i++)
886
string part = mifFile.readString ();
887
if (TeStringCompare(part,"Region"))
888
TeMIFRegionDecode (mifFile, pols, index);
889
else if(TeStringCompare(part,"Pline"))
890
TeMIFPlineDecode (mifFile, ls, index);
891
else if (TeStringCompare(part,"Multipoint"))
892
TeMIFMultiPointDecode (mifFile,ps, index);