Salome HOME
Merge branch 'BR_LAND_COVER_MAP' of ssh://git.salome-platform.org/modules/hydro into...
[modules/hydro.git] / src / HYDROData / HYDROData_SinusX.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_SinusX.h"
20
21 #include <HYDROData_PolylineXY.h>
22 #include <HYDROData_Bathymetry.h>
23 #include <HYDROData_Entity.h>
24 #include <HYDROData_Document.h>
25 #include <HYDROData_Profile.h>
26 #include <HYDROData_Iterator.h>
27
28 #include <gp_XYZ.hxx>
29 #include <gp_XY.hxx>
30
31 #include <QFile>
32 #include <QFileInfo>
33 #include <QString>
34 #include <QStringList>
35 #include <QTextStream>
36 #include <QColor>
37
38 HYDROData_SinusX::HYDROData_SinusX( ) 
39 {
40 }
41
42 HYDROData_SinusX::~HYDROData_SinusX()
43 {
44 }
45
46 void HYDROData_SinusX::CollectExistingNames(Handle_HYDROData_Document theDocument)
47 {
48   HYDROData_Iterator anIter( theDocument );
49   int anInd = 0;
50   myExistingNames.clear();
51   std::vector<int> anAllowedIndexes;
52   for( ; anIter.More(); anIter.Next() )
53     myExistingNames.push_back(anIter.Current()->GetName());
54 }
55
56 QString HYDROData_SinusX::GetName(const QString& theName)
57 {
58   if (myExistingNames.contains(theName))
59   { 
60     QString aName = theName; 
61     while (myExistingNames.contains(aName)) 
62     {
63       QStringList aList = aName.split("_");
64       int aLastInd = aName.lastIndexOf("_");
65       bool IsNum = false; 
66       int anInd = -1;
67       anInd = aList.last().toInt(&IsNum);
68       if (IsNum)
69       {
70         aName = aName.left(aLastInd) + "_";
71         aName+= QString::number(++anInd);
72       }
73       else
74         aName = theName + "_0";
75     }
76
77     myExistingNames.push_back(aName);
78     return aName;
79   }
80   else
81   {
82     myExistingNames.push_back(theName);
83     return theName;
84   }
85
86 }
87
88
89 bool HYDROData_SinusX::Import(const QString& theFilePath, Handle(HYDROData_Document) theDocument, NCollection_Sequence<Handle_HYDROData_Entity>& theEntities)
90 {
91   if ( theFilePath.isEmpty() )
92   { 
93     return false;
94   }
95
96   QString anExt = theFilePath.split('.', QString::SkipEmptyParts).back();
97
98   if (anExt == "sx")
99   {
100     QFile aFile (theFilePath);
101     
102     aFile.open(QIODevice::ReadOnly);
103
104     Parse(aFile);
105    
106     CollectExistingNames(theDocument);
107     SXToHydro(theDocument, theEntities);
108     
109     aFile.close();
110     
111     return true;
112   }
113   else
114     return false;
115
116 }
117
118 void HYDROData_SinusX::SXToHydro(Handle(HYDROData_Document) theDocument, NCollection_Sequence<Handle_HYDROData_Entity>& theEntities)
119
120   for ( size_t i = 0; i < myCurveBlocks.size(); i++ )
121   {
122     if (myCurveBlocks[i].myType == 4) ///  scatter plot -> to bathy
123     {
124       Handle(HYDROData_Bathymetry) aBath = Handle(HYDROData_Bathymetry)::DownCast( theDocument->CreateObject( KIND_BATHYMETRY ) );
125       HYDROData_Bathymetry::AltitudePoints aAPoints;
126       for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
127         aAPoints.Append(gp_XYZ (myCurveBlocks[i].myXYZPoints[j]));
128
129       aBath->SetAltitudePoints(aAPoints);
130       aBath->SetName(GetName(myCurveBlocks[i].myName + "_bath"));
131       theEntities.Append(aBath);
132     }
133     if (myCurveBlocks[i].myType == 1 || myCurveBlocks[i].myType == 3)
134     {
135       NCollection_Sequence<gp_XYZ> aPoints;
136       for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
137         aPoints.Append(gp_XYZ (myCurveBlocks[i].myXYZPoints[j]));
138       /*if (myCurveBlocks[i].myIsClosed)
139         aPoints.Append(gp_XYZ (myCurveBlocks[i].myXYZPoints[0]));*/
140       Handle(HYDROData_ProfileUZ) aProfileUZ = Handle(HYDROData_ProfileUZ)::DownCast( theDocument->CreateObject( KIND_PROFILEUZ ) );
141       Handle(HYDROData_PolylineXY) aPolyXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) );
142       aPolyXY->AddSection( "",  
143         myCurveBlocks[i].myIsSpline ? HYDROData_PolylineXY::SECTION_SPLINE : HYDROData_PolylineXY::SECTION_POLYLINE, 
144         myCurveBlocks[i].myIsClosed ? true : false); 
145       aProfileUZ->CalculateAndAddPoints(aPoints, aPolyXY);
146       Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( theDocument->CreateObject( KIND_PROFILE ) );
147       aProfile->SetParametricPoints(aProfileUZ->GetPoints());
148       aPolyXY->SetName(GetName(myCurveBlocks[i].myName + "_polyXY"));
149       aProfileUZ->SetName(GetName(myCurveBlocks[i].myName + "_profileUZ"));
150       aProfile->SetName(GetName(myCurveBlocks[i].myName + "_profile"));
151       aPolyXY->SetWireColor(HYDROData_PolylineXY::DefaultWireColor());
152       theEntities.Append(aPolyXY);
153       theEntities.Append(aProfileUZ);
154       theEntities.Append(aProfile);
155     }
156     if (myCurveBlocks[i].myType == 2)
157     {
158       if (myCurveBlocks[i].myCurvePlane == 2)
159       {
160         if (myCurveBlocks[i].myAdditionalCurveInfo.size() == 4)
161         {
162           Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( theDocument->CreateObject( KIND_PROFILE ) );
163           HYDROData_ProfileUZ::PointsList aPointList;
164           for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
165             aPointList.Append(gp_XY (myCurveBlocks[i].myXYZPoints[j].X(), myCurveBlocks[i].myXYZPoints[j].Z()));
166           aProfile->GetProfileUZ()->SetSectionType(0,  myCurveBlocks[i].myIsSpline ? HYDROData_PolylineXY::SECTION_SPLINE : HYDROData_PolylineXY::SECTION_POLYLINE);
167           aProfile->GetProfileUZ()->SetSectionClosed(0, myCurveBlocks[i].myIsClosed ? true : false);
168           aProfile->SetParametricPoints(aPointList);
169           if ( ! (myCurveBlocks[i].myAdditionalCurveInfo[0] == 0 &&  myCurveBlocks[i].myAdditionalCurveInfo[1] == 0 && 
170             myCurveBlocks[i].myAdditionalCurveInfo[2] == 0 && myCurveBlocks[i].myAdditionalCurveInfo[3] == 0) )
171           {
172             aProfile->SetLeftPoint(gp_XY(myCurveBlocks[i].myAdditionalCurveInfo[0], myCurveBlocks[i].myAdditionalCurveInfo[1]));
173             aProfile->SetRightPoint(gp_XY(myCurveBlocks[i].myAdditionalCurveInfo[2], myCurveBlocks[i].myAdditionalCurveInfo[3]));
174             aProfile->Update();
175           }
176           aProfile->SetName(GetName(myCurveBlocks[i].myName + "_profile"));
177           theEntities.Append(aProfile);
178         }
179       }
180       if (myCurveBlocks[i].myCurvePlane == 0)
181       {
182         Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( theDocument->CreateObject( KIND_PROFILE ) );
183         HYDROData_Profile::ProfilePoints aPointList;
184         for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
185           aPointList.Append(myCurveBlocks[i].myXYZPoints[j]);
186         aProfile->GetProfileUZ()->SetSectionType(0,  myCurveBlocks[i].myIsSpline ? HYDROData_PolylineXY::SECTION_SPLINE : HYDROData_PolylineXY::SECTION_POLYLINE);
187         aProfile->GetProfileUZ()->SetSectionClosed(0, myCurveBlocks[i].myIsClosed ? true : false);
188         aProfile->SetProfilePoints(aPointList);
189         aProfile->SetName(GetName(myCurveBlocks[i].myName + "_profile"));
190         theEntities.Append(aProfile);
191       }
192     }
193   }
194
195 }
196  
197
198 bool HYDROData_SinusX::Parse(QFile& theFile)
199 {
200   if ( !theFile.isOpen() )
201     return false;
202
203   QString aLine;
204   QString aBLine;
205   QStringList aList;
206   QStringList aBList;
207   myCurveBlocks.clear();
208   bool aTotStat = true;
209
210   aLine = theFile.readLine().simplified();
211   aList = aLine.split( ' ', QString::SkipEmptyParts );
212
213   for (;!theFile.atEnd();) 
214   {
215     if (aList[0] == "B" && (aList[1] == "C" || aList[1] == "P" || aList[1] == "N" || aList[1] == "S" ))
216     {  
217       HYDROGUI_CurveBlock aCurveBlockInfo;
218       if (aList[1] == "C")
219         aCurveBlockInfo.myType = 1;
220       else if (aList[1] == "P")
221         aCurveBlockInfo.myType = 2;
222       else if (aList[1] == "N")
223         aCurveBlockInfo.myType = 3;
224       else if (aList[1] == "S")
225         aCurveBlockInfo.myType = 4;
226
227       if (aList.size() == 9)
228       {
229         for (int j = 2; j < 8; j++)
230           aCurveBlockInfo.myRefCoords.push_back(aList[j].toDouble());
231         aCurveBlockInfo.myRefRatio = aList[8].toDouble();
232       }
233
234       QString Name;
235       do
236       {
237         aBLine = theFile.readLine().simplified();
238         aBList = aBLine.split( ' ', QString::SkipEmptyParts );
239          
240         if (aBList[0] == "CP")
241         {
242           if (aBList.size() == 2 && (aBList[1] == "0" || aBList[1] == "1" || aBList[1] == "2"))
243             aCurveBlockInfo.myCurvePlane = aBList[1].toInt();
244           else if (aBList.size() == 3 && (aBList[1] == "0" || aBList[1] == "1") && (aBList[2] == "0" || aBList[2] == "1"))
245           {
246             aCurveBlockInfo.myIsClosed = aBList[1].toInt();
247             aCurveBlockInfo.myIsSpline = aBList[2].toInt();
248           }
249           else
250           {
251             for (int j = 1; j < aBList.size(); j++)
252               aCurveBlockInfo.myAdditionalCurveInfo.push_back(aBList[j].toDouble());
253           }
254         }
255         if (aBList[0] == "CN")
256         {
257            for (int i = 1; i < aBList.size(); i++)
258              Name += aBList[i] + "_"; 
259            Name.remove(Name.size() - 1, 1);
260            aCurveBlockInfo.myName = Name;
261         }
262       } while (!theFile.atEnd() && aBLine[0] == 'C' );
263
264       bool aStat;
265       aTotStat = true;
266       do
267       {
268         if (aBList.size() >= 3 && aBLine[0] != 'B' && aBLine[0] != 'C') {
269           gp_XYZ anXYZ;
270           anXYZ.SetX (aBList[0].toDouble(&aStat));  
271           aTotStat = aTotStat && aStat;
272           anXYZ.SetY (aBList[1].toDouble(&aStat));
273           aTotStat = aTotStat && aStat;
274           anXYZ.SetZ (aBList[2].toDouble(&aStat));
275           aTotStat = aTotStat && aStat;
276
277           aCurveBlockInfo.myXYZPoints.push_back(anXYZ);
278           
279           aBLine = theFile.readLine().simplified();
280           aBList = aBLine.split( ' ', QString::SkipEmptyParts );
281         }
282         else 
283           break;
284     
285       } while (!theFile.atEnd() || !aBLine.isEmpty());
286       if (aTotStat)
287         myCurveBlocks.push_back(aCurveBlockInfo);
288
289       aLine = aBLine;
290       aList = aBList;
291
292     }
293     else
294     {
295       aLine = theFile.readLine().simplified();
296       aList = aLine.split( ' ', QString::SkipEmptyParts );
297     }
298
299   }
300
301   return true;
302
303 }
304
305 bool HYDROData_SinusX::Export(const QString& theFilePath, const NCollection_Sequence<Handle_HYDROData_Entity>& theEntities)
306 {
307   if ( theFilePath.isEmpty() )
308   { 
309     return false;
310   }
311
312   QString anExt = theFilePath.split('.', QString::SkipEmptyParts).back();
313
314   if (anExt == "sx")
315   {
316     QFile aFile (theFilePath);
317     
318     aFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
319
320     HydroToSX(aFile, theEntities);
321     
322     aFile.close();
323     
324     return true;
325   }
326   else
327     return false;
328
329 }
330
331 void HYDROData_SinusX::HydroToSX(QFile& theFile, const NCollection_Sequence<Handle_HYDROData_Entity>& theEntities)
332 {
333   QTextStream aTextStream(&theFile);
334   aTextStream << "C  Generated by HYDRO Module\n";
335   aTextStream << "C\n";
336
337   for (int i = 1; i <= theEntities.Size(); i++)
338   {
339     Handle_HYDROData_Entity anEnt = theEntities.Value(i);
340     if (anEnt->IsKind( STANDARD_TYPE(HYDROData_Bathymetry) ))
341     {
342       Handle(HYDROData_Bathymetry) aBathy = Handle(HYDROData_Bathymetry)::DownCast( anEnt );
343       HYDROData_Bathymetry::AltitudePoints anXYZPoints = aBathy->GetAltitudePoints(true);
344       //Write to stream
345       aTextStream << "B S\n";
346       aTextStream << "CN " << aBathy->GetName() << "\n";
347       aTextStream << "CP 0 0\n";
348       aTextStream << "CP 0\n";
349       for (int j = anXYZPoints.Lower(); j <= anXYZPoints.Upper(); j++)
350         aTextStream << " " << QString::number(anXYZPoints(j).X(), 'f', 3)  
351                     << " " << QString::number(anXYZPoints(j).Y(), 'f', 3)  
352                     << " " << QString::number(anXYZPoints(j).Z(), 'f', 3) << "\n"; 
353     }
354     else if (anEnt->IsKind( STANDARD_TYPE(HYDROData_PolylineXY) ))
355     {
356       Handle(HYDROData_PolylineXY) aPolyXY = Handle(HYDROData_PolylineXY)::DownCast( anEnt );
357       for (int j = 0; j < aPolyXY->NbSections(); j++)
358       { 
359         //Collect data
360         bool IsClosed = aPolyXY->IsClosedSection(j);
361         bool IsSpline = false;
362         if (aPolyXY->GetSectionType(j) == HYDROData_PolylineXY::SECTION_SPLINE)
363           IsSpline = true;
364         HYDROData_PolylineXY::PointsList anXYPoints = aPolyXY->GetPoints(j, true);
365         //Write to stream
366         aTextStream << "B N\n";
367         aTextStream << "CN " << aPolyXY->GetName() << "\n";
368         aTextStream << "CP " << IsClosed << " " << IsSpline << "\n";
369         aTextStream << "CP 0.0\n";
370         aTextStream << "CP 0\n";
371         if (aPolyXY->NbSections() > 1)
372           aTextStream << "C " << aPolyXY->GetName() << "_section_" << QString::number(j) << "\n";
373         for (int k = anXYPoints.Lower(); k <= anXYPoints.Upper(); k++)
374          aTextStream << " " << QString::number(anXYPoints(k).X(), 'f', 3)  
375                      << " " << QString::number(anXYPoints(k).Y(), 'f', 3)  
376                      << " 0.000\n"; 
377       }
378     }
379     else if (anEnt->IsKind( STANDARD_TYPE(HYDROData_Profile) ))
380     {
381       //Collect data
382       Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( anEnt );
383       HYDROData_ProfileUZ::PointsList aPointList = aProfile->GetParametricPoints();
384       bool IsClosed = aProfile->GetProfileUZ(false)->IsClosedSection(0);;
385       bool IsSpline = false;
386       if (aProfile->GetProfileUZ(false)->GetSectionType(0) == HYDROData_PolylineXY::SECTION_SPLINE)
387         IsSpline = true;
388       //Write to stream
389       aTextStream << "B P\n";
390       aTextStream << "CN " << aProfile->GetName() << "\n";
391       aTextStream << "CP " << IsClosed << " " << IsSpline << "\n";
392       gp_XY aLeftPoint(0.0, 0.0);
393       gp_XY aRightPoint(0.0, 0.0);
394       if (aProfile->GetLeftPoint(aLeftPoint, true) && aProfile->GetRightPoint(aRightPoint, true))
395         aTextStream << "CP " << QString::number(aLeftPoint.X(), 'f', 3) << " " <<
396                                 QString::number(aLeftPoint.Y(), 'f', 3) << " " <<
397                                 QString::number(aRightPoint.X(), 'f', 3) << " " <<
398                                 QString::number(aRightPoint.Y(), 'f', 3) << "\n";
399       else
400         aTextStream << "CP 0.0 0.0 0.0 0.0\n";
401       aTextStream << "CP 2\n";
402       for (int k = aPointList.Lower(); k <= aPointList.Upper(); k++)
403          aTextStream << " " << QString::number(aPointList(k).X(), 'f', 3)  
404                      << " 0.000 "
405                      << QString::number(aPointList(k).Y(), 'f', 3) << "\n";  
406     }
407   }
408 }