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