Salome HOME
8bee17ad234dc0f49745827ba054f2c2cabe8173
[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,
90   NCollection_Sequence<Handle(HYDROData_Entity)>& theEntities)
91 {
92   if ( theFilePath.isEmpty() )
93   { 
94     return false;
95   }
96
97   QString anExt = theFilePath.split('.', QString::SkipEmptyParts).back();
98
99   if (anExt == "sx")
100   {
101     QFile aFile (theFilePath);
102     
103     aFile.open(QIODevice::ReadOnly);
104
105     Parse(aFile);
106    
107     CollectExistingNames(theDocument);
108     SXToHydro(theDocument, theEntities);
109     
110     aFile.close();
111     
112     return true;
113   }
114   else
115     return false;
116
117 }
118
119 void HYDROData_SinusX::SXToHydro(Handle(HYDROData_Document) theDocument, NCollection_Sequence<Handle(HYDROData_Entity)>& theEntities)
120
121   for ( size_t i = 0; i < myCurveBlocks.size(); i++ )
122   {
123     if (myCurveBlocks[i].myType == 4) ///  scatter plot -> to bathy
124     {
125       Handle(HYDROData_Bathymetry) aBath = Handle(HYDROData_Bathymetry)::DownCast( theDocument->CreateObject( KIND_BATHYMETRY ) );
126       HYDROData_Bathymetry::AltitudePoints aAPoints;
127       for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
128       {
129         gp_XYZ aLocalPoint = gp_XYZ (myCurveBlocks[i].myXYZPoints[j]);
130         theDocument->Transform(aLocalPoint, true);
131         aAPoints.Append(aLocalPoint);
132       }
133
134       aBath->SetAltitudePoints(aAPoints);
135       aBath->SetName(GetName(myCurveBlocks[i].myName));
136       theEntities.Append(aBath);
137     }
138     if (myCurveBlocks[i].myType == 1 || myCurveBlocks[i].myType == 3) // XYZ curve or isocontour
139     {
140       NCollection_Sequence<gp_XYZ> aPoints;
141       for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
142       {
143         gp_XYZ aLocalPoint = gp_XYZ (myCurveBlocks[i].myXYZPoints[j]);
144         theDocument->Transform(aLocalPoint, true);
145         aPoints.Append(aLocalPoint);
146       }
147       /*if (myCurveBlocks[i].myIsClosed)
148         aPoints.Append(gp_XYZ (myCurveBlocks[i].myXYZPoints[0]));*/
149       Handle(HYDROData_ProfileUZ) aProfileUZ = Handle(HYDROData_ProfileUZ)::DownCast( theDocument->CreateObject( KIND_PROFILEUZ ) );
150       Handle(HYDROData_PolylineXY) aPolyXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) );
151       aPolyXY->AddSection( "",  
152         myCurveBlocks[i].myIsSpline ? HYDROData_PolylineXY::SECTION_SPLINE : HYDROData_PolylineXY::SECTION_POLYLINE, 
153         myCurveBlocks[i].myIsClosed ? true : false); 
154       aProfileUZ->CalculateAndAddPoints(aPoints, aPolyXY);
155       Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( theDocument->CreateObject( KIND_PROFILE ) );
156       aProfile->SetParametricPoints(aProfileUZ->GetPoints());
157       aPolyXY->SetName(GetName(myCurveBlocks[i].myName));
158       aProfileUZ->SetName(GetName(myCurveBlocks[i].myName));
159       aProfile->SetName(GetName(myCurveBlocks[i].myName));
160       aPolyXY->SetWireColor(HYDROData_PolylineXY::DefaultWireColor());
161       theEntities.Append(aPolyXY);
162       theEntities.Append(aProfileUZ);
163       theEntities.Append(aProfile);
164     }
165     if (myCurveBlocks[i].myType == 2) // XYZ profile
166     {
167       if (myCurveBlocks[i].myCurvePlane == 2) // plane XoZ
168       {
169         if (myCurveBlocks[i].myAdditionalCurveInfo.size() == 4)
170         {
171           Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( theDocument->CreateObject( KIND_PROFILE ) );
172           HYDROData_ProfileUZ::PointsList aPointList;
173           for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
174             aPointList.Append(gp_XY (myCurveBlocks[i].myXYZPoints[j].X(), myCurveBlocks[i].myXYZPoints[j].Z()));
175           aProfile->GetProfileUZ()->SetSectionType(0,  myCurveBlocks[i].myIsSpline ? HYDROData_PolylineXY::SECTION_SPLINE : HYDROData_PolylineXY::SECTION_POLYLINE);
176           aProfile->GetProfileUZ()->SetSectionClosed(0, myCurveBlocks[i].myIsClosed ? true : false);
177           aProfile->SetParametricPoints(aPointList);
178           if ( ! (myCurveBlocks[i].myAdditionalCurveInfo[0] == 0 &&  myCurveBlocks[i].myAdditionalCurveInfo[1] == 0 && 
179             myCurveBlocks[i].myAdditionalCurveInfo[2] == 0 && myCurveBlocks[i].myAdditionalCurveInfo[3] == 0) )
180           { // georeferenced profile
181             double xl = myCurveBlocks[i].myAdditionalCurveInfo[0];
182             double yl = myCurveBlocks[i].myAdditionalCurveInfo[1];
183             double xr = myCurveBlocks[i].myAdditionalCurveInfo[2];
184             double yr = myCurveBlocks[i].myAdditionalCurveInfo[3];
185             theDocument->Transform(xl, yl , true);
186             theDocument->Transform(xr, yr , true);
187             aProfile->SetLeftPoint(gp_XY(xl, yl));
188             aProfile->SetRightPoint(gp_XY(xr, yr));
189             aProfile->Update();
190           }
191           aProfile->SetName(GetName(myCurveBlocks[i].myName));
192           theEntities.Append(aProfile);
193         }
194       }
195       if (myCurveBlocks[i].myCurvePlane == 0) // plane XoY
196       {
197         Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( theDocument->CreateObject( KIND_PROFILE ) );
198         HYDROData_Profile::ProfilePoints aPointList;
199         for (size_t j = 0; j < myCurveBlocks[i].myXYZPoints.size(); j++)
200         {
201           gp_XYZ aLocalPoint = gp_XYZ (myCurveBlocks[i].myXYZPoints[j]);
202           theDocument->Transform(aLocalPoint, true);
203           aPointList.Append(aLocalPoint);
204         }
205         aProfile->GetProfileUZ()->SetSectionType(0,  myCurveBlocks[i].myIsSpline ? HYDROData_PolylineXY::SECTION_SPLINE : HYDROData_PolylineXY::SECTION_POLYLINE);
206         aProfile->GetProfileUZ()->SetSectionClosed(0, myCurveBlocks[i].myIsClosed ? true : false);
207         aProfile->SetProfilePoints(aPointList);
208         aProfile->SetName(GetName(myCurveBlocks[i].myName));
209         theEntities.Append(aProfile);
210       }
211     }
212   }
213
214 }
215  
216
217 bool HYDROData_SinusX::Parse(QFile& theFile)
218 {
219   if ( !theFile.isOpen() )
220     return false;
221
222   QString aLine;
223   QString aBLine;
224   QStringList aList;
225   QStringList aBList;
226   myCurveBlocks.clear();
227   bool aTotStat = true;
228
229   aLine = theFile.readLine().simplified();
230   aList = aLine.split( ' ', QString::SkipEmptyParts );
231
232   for (;!theFile.atEnd();) 
233   {
234     if (aList[0] == "B" && (aList[1] == "C" || aList[1] == "P" || aList[1] == "N" || aList[1] == "S" ))
235     {  
236       HYDROGUI_CurveBlock aCurveBlockInfo;
237       if (aList[1] == "C")
238         aCurveBlockInfo.myType = 1; // XYZ curve
239       else if (aList[1] == "P")
240         aCurveBlockInfo.myType = 2; // XYZ profile
241       else if (aList[1] == "N")
242         aCurveBlockInfo.myType = 3; // isocontour
243       else if (aList[1] == "S")
244         aCurveBlockInfo.myType = 4; // Scatter plot
245
246       if (aList.size() == 9)
247       {
248         for (int j = 2; j < 8; j++)
249           aCurveBlockInfo.myRefCoords.push_back(aList[j].toDouble());
250         aCurveBlockInfo.myRefRatio = aList[8].toDouble();
251       }
252
253       QString Name;
254       do
255       {
256         aBLine = theFile.readLine().simplified();
257         aBList = aBLine.split( ' ', QString::SkipEmptyParts );
258          
259         if (aBList[0] == "CP")
260         {
261           if (aBList.size() == 2 && (aBList[1] == "0" || aBList[1] == "1" || aBList[1] == "2"))
262             aCurveBlockInfo.myCurvePlane = aBList[1].toInt();
263           else if (aBList.size() == 3 && (aBList[1] == "0" || aBList[1] == "1") && (aBList[2] == "0" || aBList[2] == "1"))
264           {
265             aCurveBlockInfo.myIsClosed = aBList[1].toInt();
266             aCurveBlockInfo.myIsSpline = aBList[2].toInt();
267           }
268           else
269           {
270             for (int j = 1; j < aBList.size(); j++)
271               aCurveBlockInfo.myAdditionalCurveInfo.push_back(aBList[j].toDouble());
272           }
273         }
274         if (aBList[0] == "CN")
275         {
276            for (int i = 1; i < aBList.size(); i++)
277              Name += aBList[i] + "_";
278            if (Name.size() <= 1)
279              Name = "noname_";
280            Name.remove(Name.size() - 1, 1);
281            aCurveBlockInfo.myName = Name;
282         }
283       } while (!theFile.atEnd() && aBLine[0] == 'C' );
284
285       bool aStat;
286       aTotStat = true;
287       do
288       {
289         if (aBList.size() >= 3 && aBLine[0] != 'B' && aBLine[0] != 'C') {
290           gp_XYZ anXYZ;
291           anXYZ.SetX (aBList[0].toDouble(&aStat));  
292           aTotStat = aTotStat && aStat;
293           anXYZ.SetY (aBList[1].toDouble(&aStat));
294           aTotStat = aTotStat && aStat;
295           anXYZ.SetZ (aBList[2].toDouble(&aStat));
296           aTotStat = aTotStat && aStat;
297
298           aCurveBlockInfo.myXYZPoints.push_back(anXYZ);
299           
300           aBLine = theFile.readLine().simplified();
301           aBList = aBLine.split( ' ', QString::SkipEmptyParts );
302         }
303         else 
304           break;
305     
306       } while (!theFile.atEnd() || !aBLine.isEmpty());
307       if (aTotStat)
308         myCurveBlocks.push_back(aCurveBlockInfo);
309
310       aLine = aBLine;
311       aList = aBList;
312
313     }
314     else
315     {
316       aLine = theFile.readLine().simplified();
317       aList = aLine.split( ' ', QString::SkipEmptyParts );
318     }
319
320   }
321
322   return true;
323
324 }
325
326 bool HYDROData_SinusX::Export(const QString& theFilePath, const NCollection_Sequence<Handle(HYDROData_Entity)>& theEntities)
327 {
328   if ( theFilePath.isEmpty() )
329   { 
330     return false;
331   }
332
333   QString anExt = theFilePath.split('.', QString::SkipEmptyParts).back();
334
335   if (anExt == "sx")
336   {
337     QFile aFile (theFilePath);
338     
339     aFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
340
341     HydroToSX(aFile, theEntities);
342     
343     aFile.close();
344     
345     return true;
346   }
347   else
348     return false;
349
350 }
351
352 void HYDROData_SinusX::HydroToSX(QFile& theFile, const NCollection_Sequence<Handle(HYDROData_Entity)>& theEntities)
353 {
354   QTextStream aTextStream(&theFile);
355   aTextStream << "C  Generated by HYDRO Module\n";
356   aTextStream << "C\n";
357
358   for (int i = 1; i <= theEntities.Size(); i++)
359   {
360     Handle(HYDROData_Entity) anEnt = theEntities.Value(i);
361     if (anEnt->IsKind( STANDARD_TYPE(HYDROData_Bathymetry) ))
362     {
363       Handle(HYDROData_Bathymetry) aBathy = Handle(HYDROData_Bathymetry)::DownCast( anEnt );
364       HYDROData_Bathymetry::AltitudePoints anXYZPoints = aBathy->GetAltitudePoints(true);
365       //Write to stream
366       aTextStream << "B S\n";
367       aTextStream << "CN " << aBathy->GetName() << "\n";
368       aTextStream << "CP 0 0\n";
369       aTextStream << "CP 0\n";
370       for (int j = anXYZPoints.Lower(); j <= anXYZPoints.Upper(); j++)
371         aTextStream << " " << QString::number(anXYZPoints(j).X(), 'f', 3)  
372                     << " " << QString::number(anXYZPoints(j).Y(), 'f', 3)  
373                     << " " << QString::number(anXYZPoints(j).Z(), 'f', 3) << "\n"; 
374     }
375     else if (anEnt->IsKind( STANDARD_TYPE(HYDROData_PolylineXY) ))
376     {
377       Handle(HYDROData_PolylineXY) aPolyXY = Handle(HYDROData_PolylineXY)::DownCast( anEnt );
378       for (int j = 0; j < aPolyXY->NbSections(); j++)
379       { 
380         //Collect data
381         bool IsClosed = aPolyXY->IsClosedSection(j);
382         bool IsSpline = false;
383         if (aPolyXY->GetSectionType(j) == HYDROData_PolylineXY::SECTION_SPLINE)
384           IsSpline = true;
385         HYDROData_PolylineXY::PointsList anXYPoints = aPolyXY->GetPoints(j, true);
386         //Write to stream
387         aTextStream << "B N\n";
388         aTextStream << "CN " << aPolyXY->GetName() << "\n";
389         aTextStream << "CP " << IsClosed << " " << IsSpline << "\n";
390         aTextStream << "CP 0.0\n";
391         aTextStream << "CP 0\n";
392         if (aPolyXY->NbSections() > 1)
393           aTextStream << "C " << aPolyXY->GetName() << "_section_" << QString::number(j) << "\n";
394         for (int k = anXYPoints.Lower(); k <= anXYPoints.Upper(); k++)
395          aTextStream << " " << QString::number(anXYPoints(k).X(), 'f', 3)  
396                      << " " << QString::number(anXYPoints(k).Y(), 'f', 3)  
397                      << " 0.000\n"; 
398       }
399     }
400     else if (anEnt->IsKind( STANDARD_TYPE(HYDROData_Profile) ))
401     {
402       //Collect data
403       Handle(HYDROData_Profile) aProfile = Handle(HYDROData_Profile)::DownCast( anEnt );
404       HYDROData_ProfileUZ::PointsList aPointList = aProfile->GetParametricPoints();
405       bool IsClosed = aProfile->GetProfileUZ(false)->IsClosedSection(0);;
406       bool IsSpline = false;
407       if (aProfile->GetProfileUZ(false)->GetSectionType(0) == HYDROData_PolylineXY::SECTION_SPLINE)
408         IsSpline = true;
409       //Write to stream
410       aTextStream << "B P\n";
411       aTextStream << "CN " << aProfile->GetName() << "\n";
412       aTextStream << "CP " << IsClosed << " " << IsSpline << "\n";
413       gp_XY aLeftPoint(0.0, 0.0);
414       gp_XY aRightPoint(0.0, 0.0);
415       if (aProfile->GetLeftPoint(aLeftPoint, true) && aProfile->GetRightPoint(aRightPoint, true))
416         aTextStream << "CP " << QString::number(aLeftPoint.X(), 'f', 3) << " " <<
417                                 QString::number(aLeftPoint.Y(), 'f', 3) << " " <<
418                                 QString::number(aRightPoint.X(), 'f', 3) << " " <<
419                                 QString::number(aRightPoint.Y(), 'f', 3) << "\n";
420       else
421         aTextStream << "CP 0.0 0.0 0.0 0.0\n";
422       aTextStream << "CP 2\n";
423       for (int k = aPointList.Lower(); k <= aPointList.Upper(); k++)
424          aTextStream << " " << QString::number(aPointList(k).X(), 'f', 3)  
425                      << " 0.000 "
426                      << QString::number(aPointList(k).Y(), 'f', 3) << "\n";  
427     }
428   }
429 }