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