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