Salome HOME
LCM // Import/Export of SHP p.6
[modules/hydro.git] / src / HYDROData / HYDROData_ShapeFile.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include <HYDROData_ShapeFile.h>
20 #include <HYDROData_PolylineXY.h>
21 #include <HYDROData_Polyline3D.h>
22 #include <HYDROData_Bathymetry.h>
23 #include <HYDROData_Profile.h>
24 #include <HYDROData_Iterator.h>
25 #include <HYDROData_LandCoverMap.h>
26
27 #include <QFile>
28 #include <QFileInfo>
29 #include <TopoDS.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopoDS_Wire.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <BRep_Tool.hxx>
36 #include <Precision.hxx>
37 #include <Handle_Geom_Curve.hxx>
38 #include <Handle_Geom_Line.hxx>
39 #include <Handle_Geom_TrimmedCurve.hxx>
40 #include <Geom_TrimmedCurve.hxx>
41 #include <BRepBuilderAPI_MakeEdge.hxx>
42 #include <BRepBuilderAPI_MakeWire.hxx>
43 #include <BRepBuilderAPI_MakeFace.hxx>
44 #include <gp_Pln.hxx>
45 #include <BRepLib.hxx>
46 #include <ShapeFix_Shape.hxx>
47 #include <TopTools_SequenceOfShape.hxx>
48 #include <QColor>
49 #include <BRepTopAdaptor_FClass2d.hxx>
50
51 #ifdef WIN32
52   #pragma warning( disable: 4996 )
53 #endif
54
55 HYDROData_ShapeFile::HYDROData_ShapeFile() : myHSHP(NULL)
56
57 }
58
59 HYDROData_ShapeFile::~HYDROData_ShapeFile()
60 {
61   Free();
62 }
63
64 void HYDROData_ShapeFile::Export(const QString& aFileName, 
65   NCollection_Sequence<Handle_HYDROData_PolylineXY> aPolyXYSeq,
66   NCollection_Sequence<Handle_HYDROData_Polyline3D> aPoly3DSeq,
67   QStringList& aNonExpList)
68 {
69   SHPHandle hSHPHandle;
70   if (!aPolyXYSeq.IsEmpty() && aPoly3DSeq.IsEmpty())
71   {
72     hSHPHandle = SHPCreate( aFileName.toAscii().data(), SHPT_ARC );        
73     for (int i = 1; i <= aPolyXYSeq.Size(); i++)
74       if (WriteObjectPolyXY(hSHPHandle, aPolyXYSeq(i)) != 1)
75         aNonExpList.append(aPolyXYSeq(i)->GetName());
76   }
77   else if (aPolyXYSeq.IsEmpty() && !aPoly3DSeq.IsEmpty())
78   {
79     hSHPHandle = SHPCreate( aFileName.toAscii().data(), SHPT_ARCZ );
80     for (int i = 1; i <= aPoly3DSeq.Size(); i++)
81       if (WriteObjectPoly3D(hSHPHandle, aPoly3DSeq(i)) != 1)
82         aNonExpList.append(aPoly3DSeq(i)->GetName());
83   }
84   if (hSHPHandle->nRecords > 0)
85     SHPClose( hSHPHandle );
86   else
87   {
88     SHPClose( hSHPHandle );
89     QString aFN = aFileName.simplified();
90     remove (aFN.toStdString().c_str());
91     remove (aFN.replace( ".shp", ".shx", Qt::CaseInsensitive).toStdString().c_str());
92   }
93 }
94
95 void HYDROData_ShapeFile::Export(const QString& aFileName,
96   const Handle_HYDROData_LandCoverMap& aLCM, QStringList& aNonExpList)
97 {
98   SHPHandle hSHPHandle;
99   if ( !aLCM.IsNull() && !aLCM->IsEmpty())
100   {
101     hSHPHandle = SHPCreate( aFileName.toAscii().data(), SHPT_POLYGON );
102     HYDROData_LandCoverMap::Iterator It( aLCM );
103     for( ; It.More(); It.Next() )
104     {
105       TopoDS_Face aFace = It.Face();
106       if (WriteObjectPolygon(hSHPHandle, aFace) != 1)
107         aNonExpList.append(aLCM->GetName() + "_" +  QString::number(It.Index()));
108     }
109   }
110   if (hSHPHandle->nRecords > 0)
111     SHPClose( hSHPHandle );
112   else
113   {
114     SHPClose( hSHPHandle );
115     QString aFN = aFileName.simplified();
116     remove (aFN.toStdString().c_str());
117     remove (aFN.replace( ".shp", ".shx", Qt::CaseInsensitive).toStdString().c_str());
118   }
119 }
120
121
122 int HYDROData_ShapeFile::WriteObjectPolyXY(SHPHandle theShpHandle, Handle_HYDROData_PolylineXY thePoly )
123 {
124   SHPObject     *aSHPObj;
125   std::vector<double> x, y;
126   std::vector<int> anPartStart;
127   
128   for (int i = 0; i < thePoly->NbSections(); i++)    
129     if (thePoly->GetSectionType(i) == HYDROData_IPolyline::SECTION_SPLINE)
130       return -1;
131
132   for (int i = 0; i < thePoly->NbSections(); i++)
133   {
134     anPartStart.push_back(x.size());
135     HYDROData_PolylineXY::PointsList aPointList = thePoly->GetPoints(i);
136     for (int j = 1; j <= aPointList.Size(); j++)
137     {
138       x.push_back( aPointList(j).X());
139       y.push_back( aPointList(j).Y()); 
140     }
141     if (thePoly->IsClosedSection(i))
142     {
143       x.push_back( aPointList(1).X());
144       y.push_back( aPointList(1).Y()); 
145     }
146   }
147     
148   aSHPObj = SHPCreateObject( SHPT_ARC, -1, thePoly->NbSections(), &anPartStart[0], NULL, x.size(), &x[0], &y[0], NULL, NULL );
149   SHPWriteObject( theShpHandle, -1, aSHPObj );
150   SHPDestroyObject( aSHPObj );
151   return 1;
152 }
153
154 int HYDROData_ShapeFile::WriteObjectPoly3D(SHPHandle theShpHandle, Handle_HYDROData_Polyline3D thePoly )
155 {
156   SHPObject     *aSHPObj;
157   std::vector<double> x, y, z;
158   std::vector<int> anPartStart;
159
160   for (int i = 0; i < thePoly->GetPolylineXY()->NbSections(); i++)    
161     if (thePoly->GetPolylineXY()->GetSectionType(i) == HYDROData_IPolyline::SECTION_SPLINE)
162       return -1;
163   
164   for (int i = 0; i < thePoly->GetPolylineXY()->NbSections(); i++)
165   {
166     anPartStart.push_back(x.size());
167     HYDROData_PolylineXY::PointsList aPointList = thePoly->GetPolylineXY()->GetPoints(i);
168     for (int j = 1; j <= aPointList.Size(); j++)
169     {
170       x.push_back( aPointList(j).X());
171       y.push_back( aPointList(j).Y()); 
172       z.push_back(thePoly->GetAltitudeObject()->GetAltitudeForPoint(gp_XY (aPointList(j).X(), aPointList(j).Y())));
173     }
174     if ( thePoly->GetPolylineXY()->IsClosedSection(i))
175     {
176       x.push_back( aPointList(1).X());
177       y.push_back( aPointList(1).Y()); 
178       z.push_back(thePoly->GetAltitudeObject()->GetAltitudeForPoint(gp_XY (aPointList(1).X(), aPointList(1).Y())));
179
180     }
181   }
182   
183   aSHPObj = SHPCreateObject( SHPT_ARCZ, -1, thePoly->GetPolylineXY()->NbSections(), &anPartStart[0], NULL, x.size(), &x[0], &y[0], &z[0], NULL );
184   SHPWriteObject( theShpHandle, -1, aSHPObj );
185   SHPDestroyObject( aSHPObj );
186   return 1;
187 }
188
189 int HYDROData_ShapeFile::WriteObjectPolygon(SHPHandle theShpHandle, const TopoDS_Shape& theInputShape )
190 {
191   if (theInputShape.IsNull())
192     return 0;
193   TopExp_Explorer anEdgeEx(theInputShape, TopAbs_EDGE);
194   for (; anEdgeEx.More(); anEdgeEx.Next()) 
195   {
196     TopoDS_Edge E = TopoDS::Edge(anEdgeEx.Current());
197     double aFP, aLP;
198     Handle_Geom_Curve aCur = BRep_Tool::Curve(E, aFP, aLP);
199     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aCur);
200     if (aLine.IsNull())
201     {
202       Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCur);
203       if (!aTC.IsNull())
204       {
205         Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aTC->BasisCurve());
206         if (aLine.IsNull())
207           return -1;
208       }
209       else
210         return -1;
211     }
212
213   }
214   if (theInputShape.ShapeType() == TopAbs_FACE)
215   {
216     ProcessFace(TopoDS::Face(theInputShape), theShpHandle);
217   }
218   else if (theInputShape.ShapeType() == TopAbs_COMPOUND)
219   {
220     TopExp_Explorer Ex(theInputShape, TopAbs_FACE);
221     for (; Ex.More(); Ex.Next()) 
222     {
223       TopoDS_Face aF = TopoDS::Face(Ex.Current());   
224       if (aF.IsNull())
225         continue;
226       ProcessFace(aF, theShpHandle);
227     }
228   }
229   else
230     return 0;
231
232   return 1;
233  
234 }
235
236 void HYDROData_ShapeFile::ProcessFace(TopoDS_Face theFace, SHPHandle theShpHandle)
237 {
238   SHPObject     *aSHPObj;
239   std::vector<double> x, y;
240   std::vector<int> anPartStart;
241   if (theFace.ShapeType() == TopAbs_FACE)
242   {
243     TopExp_Explorer Ex(theFace, TopAbs_WIRE);
244     int NbWires = 0;
245     for (; Ex.More(); Ex.Next()) 
246     {
247       TopoDS_Wire aW = TopoDS::Wire(Ex.Current());   
248       if (aW.IsNull())
249         continue;
250       NbWires++;
251       anPartStart.push_back(x.size());
252       TopExp_Explorer aVEx(aW, TopAbs_VERTEX);
253       NCollection_Sequence<gp_Pnt2d> aPnts;
254       for (; aVEx.More(); aVEx.Next())
255       {
256         TopoDS_Vertex aV = TopoDS::Vertex(aVEx.Current()); 
257         if (aV.IsNull())
258           continue;
259         gp_Pnt P = BRep_Tool::Pnt(aV);
260         aPnts.Append(gp_Pnt2d(P.X(), P.Y()));
261       }
262       NCollection_Sequence<gp_Pnt2d> aNPnts;
263       aNPnts.Append(aPnts.First());
264       for (int j = 1; j <= aPnts.Size() - 1; j++)
265       {
266         if (!aPnts(j).IsEqual(aPnts(j + 1), Precision::Confusion())) 
267           aNPnts.Append(aPnts(j + 1));
268       }
269
270       for (int j = 1; j <= aNPnts.Size(); j++)
271       { 
272         x.push_back( aNPnts(j).X());
273         y.push_back( aNPnts(j).Y()); 
274       }
275       //x.push_back( aNPnts(1).X());
276       //y.push_back( aNPnts(1).Y()); 
277     }
278     
279     aSHPObj = SHPCreateObject( SHPT_POLYGON, -1, NbWires, &anPartStart[0], NULL, x.size(), &x[0], &y[0], NULL, NULL );
280     SHPWriteObject( theShpHandle, -1, aSHPObj );
281     SHPDestroyObject( aSHPObj );
282   }
283   else
284     return;
285 }
286
287 bool HYDROData_ShapeFile::Parse(SHPHandle theHandle, ShapeType theType, int& theShapeTypeOfFile)
288 {
289   int aShapeType;
290   mySHPObjects.clear();
291   SHPGetInfo( theHandle, NULL, &aShapeType, NULL, NULL );
292   theShapeTypeOfFile = aShapeType;
293   bool ToRead = (theType == ShapeType_Polyline && (aShapeType == 3 || aShapeType == 13 || aShapeType == 23)) ||
294    (theType == ShapeType_Polygon && aShapeType == 5);
295   if (ToRead) 
296   {
297     for (int i = 0; i < theHandle->nRecords; i++) 
298       mySHPObjects.push_back(SHPReadObject(theHandle, i));
299     return true;
300   }
301   else
302     return false;
303 }
304
305 void HYDROData_ShapeFile::ReadSHPPolygon(SHPObject* anObj, int i, TopoDS_Face& F)
306 {
307   TopoDS_Wire W;
308   TopoDS_Edge E; 
309   int nParts = anObj->nParts;
310   gp_Pln pln(gp_Pnt(0,0,0), gp_Dir(0,0,1));
311
312   //Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
313   //sfs->FixFaceTool()->FixOrientationMode() = 1;
314   TopTools_SequenceOfShape aWires;
315   for ( int i = 0 ; i < nParts ; i++ )
316   { 
317     BRepBuilderAPI_MakeWire aBuilder;
318     int StartIndex = anObj->panPartStart[i];
319     int EndIndex;
320     if (i != nParts - 1)
321       EndIndex = anObj->panPartStart[i + 1];
322     else
323       EndIndex = anObj->nVertices;
324
325     for ( int k = StartIndex; k < EndIndex - 1  ; k++ )
326     {
327       gp_Pnt P1 (anObj->padfX[k], anObj->padfY[k], 0);
328       gp_Pnt P2 (anObj->padfX[k+1], anObj->padfY[k+1], 0);
329       if (P1.Distance(P2) < Precision::Confusion())
330         continue;
331       BRepBuilderAPI_MakeEdge aMakeEdge(P1, P2);
332       aBuilder.Add(TopoDS::Edge(aMakeEdge.Shape()));
333     }
334     
335     aBuilder.Build();
336     W = TopoDS::Wire(aBuilder.Shape());
337     W.Orientation(TopAbs_FORWARD);
338     BRepBuilderAPI_MakeFace aDB(pln, W);
339     TopoDS_Face aDummyFace = TopoDS::Face(aDB.Shape());
340     BRepTopAdaptor_FClass2d FClass(aDummyFace, Precision::PConfusion());
341     if ( i == 0 && FClass.PerformInfinitePoint() == TopAbs_OUT) 
342       W.Reverse();
343     if ( i > 0 && FClass.PerformInfinitePoint() != TopAbs_IN) 
344       W.Reverse();
345    
346     aWires.Append(W);
347   }
348   
349   BRepBuilderAPI_MakeFace aFBuilder(pln, TopoDS::Wire(aWires(1)));
350   for (int i = 2; i <= aWires.Length(); i++)
351     aFBuilder.Add(TopoDS::Wire(aWires(i)));
352   F = TopoDS::Face(aFBuilder.Shape());
353
354   BRepLib::BuildCurves3d(F);  
355 }
356
357 int HYDROData_ShapeFile::ImportPolygons(const QString theFileName, QStringList& thePolygonsList, TopTools_SequenceOfShape& theFaces, int& theShapeTypeOfFile)
358 {
359   Free();
360   int Stat = TryOpenShapeFile(theFileName);
361   if (Stat != 0)
362     return Stat;
363   myHSHP = SHPOpen( theFileName.toAscii().data(), "rb" );
364   if (!Parse(myHSHP, HYDROData_ShapeFile::ShapeType_Polygon, theShapeTypeOfFile))
365     return 0;
366   for (size_t i = 0; i < mySHPObjects.size(); i++)
367     thePolygonsList.append("polygon_" + QString::number(i + 1));
368    
369   TopoDS_Face aF;
370   if (myHSHP->nShapeType == 5)
371   {
372     for (size_t i = 0; i < mySHPObjects.size(); i++) 
373     {
374        ReadSHPPolygon(mySHPObjects[i], i, aF);
375        theFaces.Append(aF);
376     }
377     return 1;
378   }
379   else
380     return 0;
381 }
382
383 void HYDROData_ShapeFile::Free()
384 {  
385   for (size_t i = 0; i < mySHPObjects.size(); i++ )
386     free (mySHPObjects[i]);
387
388   mySHPObjects.clear();
389   if (myHSHP != NULL)
390   {
391     SHPClose(myHSHP);
392     myHSHP = NULL; 
393   }
394 }
395
396
397 void HYDROData_ShapeFile::ReadSHPPolyXY(Handle(HYDROData_Document) theDocument, SHPObject* anObj, QString theFileName, 
398   int theInd, NCollection_Sequence<Handle_HYDROData_Entity>& theEntities)
399 {
400
401   Handle(HYDROData_PolylineXY) aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) );
402   
403   int nParts = anObj->nParts;
404   for ( int i = 0 ; i < nParts ; i++ )
405   {
406     int StartIndex = anObj->panPartStart[i];
407     int EndIndex;
408     if (i != nParts - 1)
409       EndIndex = anObj->panPartStart[i + 1];
410     else
411       EndIndex = anObj->nVertices;
412
413     bool IsClosed = false;
414     HYDROData_PolylineXY::SectionType aSectType = HYDROData_PolylineXY::SECTION_POLYLINE; 
415     if (anObj->padfX[StartIndex] == anObj->padfX[EndIndex - 1] &&
416         anObj->padfY[StartIndex] == anObj->padfY[EndIndex - 1] )
417     {
418       IsClosed = true;
419       aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, true);
420     }
421     else
422       aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, false);
423     
424     if (IsClosed)
425       EndIndex--;
426     for ( int k = StartIndex; k < EndIndex ; k++ )
427     {
428       HYDROData_PolylineXY::Point aSectPoint;
429       aSectPoint.SetX( anObj->padfX[k] );
430       aSectPoint.SetY( anObj->padfY[k] );
431       aPolylineXY->AddPoint( i, aSectPoint );
432     }
433
434   }
435   
436   aPolylineXY->SetWireColor( HYDROData_PolylineXY::DefaultWireColor() );
437   aPolylineXY->SetName( theFileName + "_PolyXY_" + QString::number(theInd) );
438   
439   aPolylineXY->Update();
440   theEntities.Append(aPolylineXY);
441
442 }
443
444 void HYDROData_ShapeFile::ReadSHPPoly3D(Handle(HYDROData_Document) theDocument, SHPObject* anObj, QString theFileName, 
445   int theInd, NCollection_Sequence<Handle_HYDROData_Entity>& theEntities)
446 {
447   Handle(HYDROData_PolylineXY) aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) );
448
449   Handle(HYDROData_Polyline3D) aPolylineObj = Handle(HYDROData_Polyline3D)::DownCast( theDocument->CreateObject( KIND_POLYLINE ) );
450
451   Handle(HYDROData_Bathymetry) aBath = Handle(HYDROData_Bathymetry)::DownCast( theDocument->CreateObject( KIND_BATHYMETRY ) );
452   HYDROData_Bathymetry::AltitudePoints aAPoints;
453
454   int nParts = anObj->nParts;
455   for ( int i = 0 ; i < nParts ; i++ )
456   {
457     //bool aSectClosure = true;
458     int StartIndex = anObj->panPartStart[i];
459     int EndIndex;
460     if (i != nParts - 1)
461       EndIndex = anObj->panPartStart[i + 1];
462     else
463       EndIndex = anObj->nVertices;
464
465     bool IsClosed = false;
466     HYDROData_PolylineXY::SectionType aSectType = HYDROData_PolylineXY::SECTION_POLYLINE; 
467     if (anObj->padfX[StartIndex] == anObj->padfX[EndIndex - 1] &&
468         anObj->padfY[StartIndex] == anObj->padfY[EndIndex - 1] &&
469         anObj->padfZ[StartIndex] == anObj->padfZ[EndIndex - 1])
470     {
471       IsClosed = true;
472       aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, true );
473     }
474     else
475       aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, false  );
476     
477     if (IsClosed)
478       EndIndex--;
479     for ( int k = StartIndex ; k < EndIndex ; k++ )
480     {
481       HYDROData_PolylineXY::Point aSectPoint;
482       aSectPoint.SetX( anObj->padfX[k] );
483       aSectPoint.SetY( anObj->padfY[k] );
484       aPolylineXY->AddPoint( i, aSectPoint );
485       aAPoints.Append(gp_XYZ (anObj->padfX[k], anObj->padfY[k], anObj->padfZ[k]));
486     }
487   }
488
489
490   QString aBathName = theFileName + "_bath_" + QString::number(theInd);
491   QString aPolyXYName = theFileName + "_polyXY_" + QString::number(theInd);
492   QString aPoly3DName = theFileName + "_poly3D_" + QString::number(theInd);
493
494   aPolylineXY->SetName( aPolyXYName );
495   aPolylineXY->SetWireColor(HYDROData_PolylineXY::DefaultWireColor());
496   aPolylineXY->Update();
497   
498   aBath->SetAltitudePoints(aAPoints);
499   aBath->SetName( aBathName );
500
501   aPolylineObj->SetPolylineXY (aPolylineXY, false);
502   aPolylineObj->SetAltitudeObject(aBath);
503
504   aPolylineObj->SetBorderColor( aPolylineObj->DefaultBorderColor() );
505   aPolylineObj->SetName( aPoly3DName );
506   
507   aPolylineObj->Update();
508   theEntities.Append(aPolylineXY);
509   theEntities.Append(aPolylineObj);
510
511 }
512
513
514
515 int HYDROData_ShapeFile::ImportPolylines(Handle(HYDROData_Document) theDocument, const QString& theFileName, 
516   NCollection_Sequence<Handle_HYDROData_Entity>& theEntities, int& theShapeTypeOfFile)
517 {
518   //Free();
519   int aStat = TryOpenShapeFile(theFileName);
520   if (aStat != 0)
521     return aStat;
522
523   HYDROData_Iterator anIter( theDocument );
524   int anInd = 0;
525   QStringList anExistingNames;
526   std::vector<int> anAllowedIndexes;
527   for( ; anIter.More(); anIter.Next() )
528     anExistingNames.push_back(anIter.Current()->GetName());
529
530   SHPHandle aHSHP;
531   aHSHP = SHPOpen( theFileName.toAscii().data(), "rb" );
532   
533   QFileInfo aFileInfo(theFileName);
534   QString aBaseFileName = aFileInfo.baseName();
535
536   if (!Parse(aHSHP, HYDROData_ShapeFile::ShapeType_Polyline, theShapeTypeOfFile))
537     return 0;
538   if (aHSHP->nShapeType == 3 || aHSHP->nShapeType == 23)
539   {
540     anInd = 0;
541     for (;anAllowedIndexes.size() < mySHPObjects.size();)
542     {
543       if (!anExistingNames.contains(aBaseFileName + "_PolyXY_" + QString::number(anInd)))
544       {
545         anAllowedIndexes.push_back(anInd);
546         anInd++;
547       }
548       else
549         anInd++;
550     }
551     
552     for (size_t i = 0; i < mySHPObjects.size(); i++ )
553     {
554       ReadSHPPolyXY(theDocument, mySHPObjects[i], aBaseFileName, anAllowedIndexes[i], theEntities);
555     }
556     aStat = 1;
557   }
558   else if (aHSHP->nShapeType == 13)
559   {
560     anInd = 0;
561     for (;anAllowedIndexes.size() < mySHPObjects.size();)
562     {
563       if (!anExistingNames.contains(aBaseFileName + "_PolyXY_" + QString::number(anInd)) &&
564           !anExistingNames.contains(aBaseFileName + "_Poly3D_" + QString::number(anInd)) &&
565           !anExistingNames.contains(aBaseFileName + "_Bath_" + QString::number(anInd)))
566       {
567         anAllowedIndexes.push_back(anInd);
568         anInd++;
569       }
570       else
571         anInd++;
572     }
573     for (size_t i = 0; i < mySHPObjects.size(); i++ )
574       ReadSHPPoly3D(theDocument, mySHPObjects[i], aBaseFileName, anAllowedIndexes[i], theEntities);
575     aStat = 1;
576   }
577   else  
578   {
579     aStat = 0;
580   }
581   
582   for (size_t i = 0; i < mySHPObjects.size(); i++ )
583     free (mySHPObjects[i]);
584
585   mySHPObjects.clear();
586   SHPClose(aHSHP);
587   return aStat;
588 }
589
590 QString HYDROData_ShapeFile::GetShapeTypeName(int theType)
591 {
592   switch (theType)
593   {
594     case 0:
595       return "null shape";
596     case 1:
597       return "point (unsupported by HYDRO)";
598     case 3:
599       return "arc/polyline (supported by HYDRO)";
600     case 5:
601       return "polygon (supported by HYDRO)";
602     case 8:
603       return "multipoint (unsupported by HYDRO)";
604     case 11:
605       return "pointZ (unsupported by HYDRO)";
606     case 13:
607       return "arcZ/polyline (supported by HYDRO)";
608     case 15:
609       return "polygonZ (unsupported by HYDRO)";
610     case 18:
611       return "multipointZ (unsupported by HYDRO)";
612     case 21:
613       return "pointM (unsupported by HYDRO)";
614     case 23:
615       return "arcM/polyline (supported by HYDRO)";
616     case 25:
617       return "polygonM (unsupported by HYDRO)";
618     case 28:
619       return "multipointM (unsupported by HYDRO)";
620     case 31:
621       return "multipatch (unsupported by HYDRO)";
622     default:
623       return "unknown";
624   }
625 }
626
627 int HYDROData_ShapeFile::TryOpenShapeFile(QString theFileName)
628 {
629   QString aSHPfile = theFileName.simplified();
630   QString aSHXfile = theFileName.simplified().replace( ".shp", ".shx", Qt::CaseInsensitive);
631   FILE* pFileSHP = NULL;
632   pFileSHP = fopen (aSHPfile.toAscii().data(), "r");
633   FILE* pFileSHX = NULL;
634   pFileSHX = fopen (aSHXfile.toAscii().data(), "r");
635
636   if (pFileSHP == NULL || pFileSHX == NULL)
637   {
638     if (pFileSHP == NULL)
639       return -1;
640     if (pFileSHX == NULL)
641       return -2;
642   }
643   
644   fclose (pFileSHP);
645   fclose (pFileSHX);
646   return 0;
647 }
648
649
650 bool HYDROData_ShapeFile::CheckDBFFileExisting(const QString& theSHPFilePath, QString& thePathToDBFFile)
651 {
652   QString aSHPfile = theSHPFilePath.simplified();
653   QString aDBFfile = theSHPFilePath.simplified().replace( ".shp", ".dbf", Qt::CaseInsensitive);
654   FILE* pFileDBF = NULL;
655   pFileDBF = fopen (aDBFfile.toAscii().data(), "r");
656
657   if (pFileDBF == NULL)
658   {
659     return false;
660   }
661   
662   fclose (pFileDBF);
663   thePathToDBFFile = aDBFfile;
664   return true;
665 }
666
667
668 bool HYDROData_ShapeFile::DBF_OpenDBF(const QString& thePathToDBFFile)
669 {
670   myHDBF = DBFOpen( thePathToDBFFile.toAscii().data(), "r" );
671   if(myHDBF != NULL)
672     return true;
673   else
674     return false;
675 }
676
677 int HYDROData_ShapeFile::DBF_GetNbFields()
678 {
679   if(myHDBF == NULL)
680     return 0;
681   return DBFGetFieldCount(myHDBF);
682 }
683
684 void HYDROData_ShapeFile::DBF_CloseDBF()
685 {
686   if(myHDBF != NULL)
687      DBFClose( myHDBF );
688 }
689
690 QStringList HYDROData_ShapeFile::DBF_GetFieldList()
691 {
692   QStringList FieldList;
693   int   nWidth, nDecimals;
694   char chField[12];
695
696   for( int i = 0; i < DBFGetFieldCount(myHDBF); i++ )
697   {
698       DBFFieldType eType;
699       eType = DBFGetFieldInfo( myHDBF, i, chField, &nWidth, &nDecimals );
700       FieldList.append(QString(chField));
701   }
702
703   return FieldList;
704 }
705
706 void HYDROData_ShapeFile::DBF_GetFieldTypeList(std::vector<DBF_FieldType>& FTVect)
707 {
708   int   nWidth, nDecimals;
709   char chField[12];
710   DBF_FieldType FT;
711   for( int i = 0; i < DBFGetFieldCount(myHDBF); i++ )
712   {
713     DBFFieldType eType;
714     eType = DBFGetFieldInfo( myHDBF, i, chField, &nWidth, &nDecimals );
715     if( eType == FTString )
716       FT = DBF_FieldType_String;
717     else if( eType == FTInteger )
718       FT = DBF_FieldType_Integer;
719     else if( eType == FTDouble )
720       FT = DBF_FieldType_Double;
721     else if( eType == FTInvalid )
722       FT = DBF_FieldType_Invalid;
723
724     FTVect.push_back(FT);
725   }
726
727 }
728
729 int HYDROData_ShapeFile::DBF_GetNbRecords()
730 {
731   if(myHDBF == NULL)
732     return 0;
733   return DBFGetRecordCount(myHDBF);
734 }
735
736 void HYDROData_ShapeFile::DBF_GetAttributeList(int theIndexOfField, std::vector<DBF_AttrValue>& theAttrV)
737 {
738   int nWidth, nDecimals;
739   char chField[12];
740   
741   for( int i = 0; i < DBFGetRecordCount(myHDBF); i++ )
742   {      
743     DBFFieldType eType;
744     DBF_AttrValue anAttr;
745     eType = DBFGetFieldInfo( myHDBF, theIndexOfField, chField, &nWidth, &nDecimals );
746
747     if( DBFIsAttributeNULL( myHDBF, i, theIndexOfField ) )
748     {
749       anAttr.myIsNull = true;
750       DBF_FieldType FT = DBF_FieldType_None;
751       if( eType == FTString )
752         FT = DBF_FieldType_String;
753       else if( eType == FTInteger )
754         FT = DBF_FieldType_Integer;
755       else if( eType == FTDouble )
756         FT = DBF_FieldType_Double;
757       else if( eType == FTInvalid )
758         FT = DBF_FieldType_Invalid;
759       anAttr.myFieldType = FT;
760     }
761     else
762     {
763       switch( eType )
764       {
765         case FTString:
766         {
767           const char* chAttr = DBFReadStringAttribute( myHDBF, i, theIndexOfField );
768           anAttr.myIsNull = false;
769           anAttr.myFieldType = DBF_FieldType_String;
770           anAttr.myRawValue = chAttr;
771           anAttr.myStrVal = QString(chAttr);
772           break;
773         }
774        
775         case FTInteger:
776         {
777           int iAttr = DBFReadIntegerAttribute( myHDBF, i, theIndexOfField );
778           anAttr.myIsNull = false;
779           anAttr.myFieldType = DBF_FieldType_Integer;
780           anAttr.myRawValue = DBFReadStringAttribute( myHDBF, i, theIndexOfField );
781           anAttr.myIntVal = iAttr;
782           break;
783         }
784           
785         case FTDouble:
786         {
787           double dAttr = DBFReadDoubleAttribute( myHDBF, i, theIndexOfField );
788           anAttr.myIsNull = false;
789           anAttr.myFieldType = DBF_FieldType_Double;
790           anAttr.myRawValue = DBFReadStringAttribute( myHDBF, i, theIndexOfField );
791           anAttr.myDoubleVal = dAttr;
792           break;
793         }
794         default:
795           break;
796       }
797     }
798     theAttrV.push_back(anAttr);
799   }
800
801 }
802
803 bool HYDROData_ShapeFile::DBF_WriteFieldAndValues(const QString& theFileName, const QString& theFieldName, DBF_FieldType theType, const std::vector<DBF_AttrValue>& theAttrV, bool bUseRawValue)
804 {
805   // Check that given field type is equal to field types of attributes values
806   for (size_t i = 0; i < theAttrV.size(); i++)
807   {
808     if (theAttrV[i].myFieldType != theType)
809       return false;
810   }
811
812   DBFHandle     hDBF;
813   hDBF = DBFCreate( theFileName.toStdString().c_str() );
814   if( hDBF == NULL )
815           return false;
816   
817   if (theType != DBF_FieldType_String && theType != DBF_FieldType_Integer && theType != DBF_FieldType_Double) 
818   {
819     DBFClose( hDBF );
820     return false; //cant handle any other cases
821   }
822
823   int nWidth = 20;
824   switch( theType )
825   {
826     case DBF_FieldType_String:
827     {
828       DBFAddField (hDBF, theFieldName.toStdString().c_str(), FTString, nWidth, 0);
829       break;
830     }
831    
832     case DBF_FieldType_Integer:
833     {
834       DBFAddField (hDBF, theFieldName.toStdString().c_str(), FTInteger, nWidth, 0);
835       break;
836     }
837       
838     case DBF_FieldType_Double:
839     {
840       DBFAddField (hDBF, theFieldName.toStdString().c_str(), FTDouble, nWidth, 0);
841       break;
842     }
843     default:
844       break;
845   }
846
847   if (DBFGetFieldCount( hDBF ) != 1) 
848   {
849     DBFClose( hDBF );
850     return false;
851   }
852   if (DBFGetRecordCount( hDBF ) != 0)
853   {
854     DBFClose( hDBF );
855     return false;
856   }
857   int stat = -1;
858
859   if (bUseRawValue)
860   {
861     for (size_t i = 0; i < theAttrV.size(); i++)
862     {
863       if (!theAttrV[i].myIsNull)
864         stat = DBFWriteStringAttribute(hDBF, (int)i, 0, theAttrV[i].myRawValue.c_str());
865       else
866         stat = DBFWriteNULLAttribute(hDBF, (int)i, 0 );
867
868       if (stat != 1)
869       {
870         DBFClose( hDBF );
871         return false;
872       }
873     }
874   }
875   else
876   {
877     for (size_t i = 0; i < theAttrV.size(); i++)
878     {
879       if (!theAttrV[i].myIsNull)
880         switch( theType )
881         {
882           case DBF_FieldType_String:
883           {
884             stat = DBFWriteStringAttribute(hDBF, (int)i, 0, theAttrV[i].myStrVal.toStdString().c_str());
885             break;
886           }
887          
888           case DBF_FieldType_Integer:
889           {
890             stat = DBFWriteIntegerAttribute(hDBF, (int)i, 0, theAttrV[i].myIntVal);
891             break;
892           }
893             
894           case DBF_FieldType_Double:
895           {
896             stat = DBFWriteDoubleAttribute(hDBF, (int)i, 0, theAttrV[i].myDoubleVal);
897             break;
898           }
899           default:
900             break;
901         }
902       else
903         stat = DBFWriteNULLAttribute(hDBF, (int)i, 0 );
904
905       if (stat != 1)
906       {
907         DBFClose( hDBF );
908         return false;
909       }
910     }
911   }
912
913   DBFClose( hDBF );
914   return true;
915
916 }