Salome HOME
417b7156e731f33f1eab08ee48b9c12f605331ef
[modules/hydro.git] / src / HYDROData / HYDROData_Tool.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_Tool.h>
20 #include <HYDROData_ArtificialObject.h>
21 #include <HYDROData_Document.h>
22 #include <HYDROData_Entity.h>
23 #include <HYDROData_Iterator.h>
24 #include <HYDROData_NaturalObject.h>
25 #include <HYDROData_ShapesGroup.h>
26 #include <QColor>
27 #include <QFile>
28 #include <QStringList>
29 #include <QTextStream>
30 #include <BRep_Tool.hxx>
31 #include <BRepAdaptor_Surface.hxx>
32 #include <BRepTopAdaptor_FClass2d.hxx>
33 #include <ElSLib.hxx>
34 #include <Geom_Curve.hxx>
35 #include <gp_Pln.hxx>
36 #include <Quantity_Color.hxx>
37 #include <TopExp_Explorer.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Wire.hxx>
42 #include <limits>
43 #include <math.h>
44
45
46 #include <BRepTools.hxx>
47 #include <NCollection_Map.hxx>
48 #include <TopExp_Explorer.hxx>
49 #include <TopoDS_Face.hxx>
50 #include <TopTools_ShapeMapHasher.hxx>
51 #include <BRep_Builder.hxx>
52 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
53 #include <TopExp.hxx>
54 #include <NCollection_List.hxx>
55 #include <TopTools_ListIteratorOfListOfShape.hxx>
56
57 static int aMaxNameId = std::numeric_limits<int>::max();
58
59 void HYDROData_Tool::WriteStringsToFile( QFile&             theFile,
60                                          const QStringList& theStrings,
61                                          const QString&     theSep )
62 {
63   if ( !theFile.isOpen() || theStrings.isEmpty() )
64     return;
65   
66   QString aWriteStr = theStrings.join( theSep );
67   if ( aWriteStr.isEmpty() )
68     return;
69
70   QTextStream anOutStream( &theFile );
71   anOutStream << aWriteStr.toUtf8() << theSep << theSep;
72 }
73
74 QString HYDROData_Tool::GenerateObjectName( const Handle(HYDROData_Document)& theDoc,
75                                             const QString&                    thePrefix,
76                                             const QStringList&                theUsedNames,
77                                             const bool                        theIsTryToUsePurePrefix )
78 {
79   QStringList aNamesList( theUsedNames );
80
81   // Collect all used names in the document
82   HYDROData_Iterator anIter( theDoc );
83   for( ; anIter.More(); anIter.Next() )
84   {
85     Handle(HYDROData_Entity) anObject = anIter.Current();
86     if( anObject.IsNull() )
87       continue;
88
89     QString anObjName = anObject->GetName();
90     if ( anObjName.isEmpty() )
91       continue;
92
93     aNamesList.append( anObjName );
94   }
95
96   QString aName;
97
98   if ( theIsTryToUsePurePrefix && !aNamesList.contains( thePrefix ) ) {
99     aName = thePrefix;
100   } else {
101     int anId = 1;
102     while( anId < aMaxNameId )
103     {
104       aName = QString( "%1_%2" ).arg( thePrefix ).arg( QString::number( anId++ ) );
105
106       // check that there are no other objects with the same name in the document
107       if ( !aNamesList.contains( aName ) )
108         break;
109     }
110   }
111
112   return aName;
113 }
114
115 bool HYDROData_Tool::IsGeometryObject( const Handle(HYDROData_Entity)& theObject )
116 {
117   if ( theObject.IsNull() )
118     return false;
119   
120   return theObject->IsKind( STANDARD_TYPE(HYDROData_ArtificialObject) ) ||
121          theObject->IsKind( STANDARD_TYPE(HYDROData_NaturalObject) );
122 }
123
124 void HYDROData_Tool::UpdateChildObjectName( const QString&                  theOldStr,
125                                             const QString&                  theNewStr,
126                                             const Handle(HYDROData_Entity)& theObject )
127 {
128   if ( theObject.IsNull() )
129     return;
130
131   QString anObjName = theObject->GetName();
132   if ( theOldStr.isEmpty() )
133   {
134     while ( anObjName.startsWith( '_' ) )
135       anObjName.remove( 0, 1 );
136
137     anObjName.prepend( theNewStr + "_" );
138   }
139   else if ( anObjName.startsWith( theOldStr ) )
140   {
141     anObjName.replace( 0, theOldStr.length(), theNewStr );
142   }
143   else
144     return;
145
146   theObject->SetName( anObjName );
147 }
148
149 QString HYDROData_Tool::GenerateNameForPython( const MapOfTreatedObjects& theTreatedObjects,
150                                                const QString&             thePrefix )
151 {
152   QString aName = thePrefix;
153   if ( !theTreatedObjects.contains( aName ) )
154     return aName;
155
156   int anId = 1;
157   while( anId < aMaxNameId )
158   {
159     aName = QString( "%1_%2" ).arg( thePrefix ).arg( QString::number( anId++ ) );
160
161     // check that there are no other objects with the same name
162     if ( !theTreatedObjects.contains( aName ) )
163       break;
164   }
165
166   return aName;
167 }
168 //======================================================================================================
169 TopAbs_State HYDROData_Tool::ComputePointState( const gp_XY& theXY, const TopoDS_Face& theFace )
170 {
171   TopAbs_State aState(TopAbs_UNKNOWN);
172   if(theFace.IsNull()) return aState;  
173   Standard_Real aTol = BRep_Tool::Tolerance(theFace);
174   BRepAdaptor_Surface Ads ( theFace, Standard_False );
175   Standard_Real toluv = Min ( Ads.UResolution(aTol), Ads.VResolution(aTol) ); 
176   const gp_Pln& aPlane = Ads.Surface().Plane();
177   gp_Pnt aPnt(theXY.X(), theXY.Y(), 0.);
178   Standard_Real aU1, aV1;
179   ElSLib::Parameters(aPlane,aPnt, aU1, aV1);
180   BRepTopAdaptor_FClass2d aClassifier( theFace, toluv ); 
181   aState = aClassifier.Perform( gp_Pnt2d(aU1, aV1), Standard_False );
182   return aState;
183 }
184
185 double HYDROData_Tool::GetAltitudeForEdge( const TopoDS_Edge& theEdge,
186                                            const gp_XY& thePoint,
187                                            double theParameterTolerance,
188                                            double theSquareDistanceTolerance,
189                                            double theInvalidAltitude )
190 {
191   double aFirst, aLast;
192   Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theEdge, aFirst, aLast );
193   if( aCurve.IsNull() )
194     return theInvalidAltitude;
195
196   gp_Pnt aFirstPnt, aLastPnt;
197
198   aCurve->D0( aFirst, aFirstPnt );
199   aCurve->D0( aLast, aLastPnt );
200
201   gp_Pnt2d aFirstPnt2d( aFirstPnt.X(), aFirstPnt.Y() );
202   gp_Pnt2d aLastPnt2d( aLastPnt.X(), aLastPnt.Y() );
203
204   double aFirstDist = 0;
205   double aLastDist = aFirstPnt2d.SquareDistance( aLastPnt2d );
206   double aNecDist = aFirstPnt2d.SquareDistance( thePoint );
207
208   while( fabs( aLast - aFirst ) > theParameterTolerance )
209   {
210     double aMid = ( aFirst + aLast ) / 2;
211     gp_Pnt aMidPnt;
212     aCurve->D0( aMid, aMidPnt );
213     double aDist = aFirstPnt2d.SquareDistance( gp_Pnt2d( aMidPnt.X(), aMidPnt.Y() ) );
214
215     if( aDist < aNecDist )
216       aFirst = aMid;
217     else
218       aLast = aMid;
219   }
220
221   double aMid = ( aFirst + aLast ) / 2;
222   gp_Pnt aMidPnt;
223   aCurve->D0( aMid, aMidPnt );
224
225   gp_Pnt2d aMidPnt2d( aMidPnt.X(), aMidPnt.Y() );
226   if( aMidPnt2d.SquareDistance( thePoint ) < theSquareDistanceTolerance )
227     return aMidPnt.Z();
228   else
229     return theInvalidAltitude;
230 }
231
232 double HYDROData_Tool::GetAltitudeForWire( const TopoDS_Wire& theWire,
233                                            const gp_XY& thePoint,
234                                            double theParameterTolerance,
235                                            double theSquareDistanceTolerance,
236                                            double theInvalidAltitude )
237 {
238   TopExp_Explorer anExp( theWire, TopAbs_EDGE );
239   for( ; anExp.More(); anExp.Next() )
240   {
241     double anAltitude = GetAltitudeForEdge( TopoDS::Edge( anExp.Current() ), thePoint,
242       theParameterTolerance, theSquareDistanceTolerance, theInvalidAltitude );
243     if( anAltitude != theInvalidAltitude )
244       return anAltitude;
245   }
246   return theInvalidAltitude;
247 }
248
249 TopoDS_Shape HYDROData_Tool::getFirstShapeFromGroup( const HYDROData_SequenceOfObjects& theGroups,
250                                                      const int                          theGroupId )
251 {
252   TopoDS_Shape aResShape;
253   if ( theGroupId < 1 || theGroupId > theGroups.Length() )
254     return aResShape;
255
256   Handle(HYDROData_ShapesGroup) aGroup =
257     Handle(HYDROData_ShapesGroup)::DownCast( theGroups.Value( theGroupId ) );
258   if ( aGroup.IsNull() )
259     return aResShape;
260
261   TopTools_SequenceOfShape aGroupShapes;
262   aGroup->GetShapes( aGroupShapes );
263
264   if ( !aGroupShapes.IsEmpty() )
265     aResShape = aGroupShapes.First();
266
267   return aResShape;
268 }
269
270 TCollection_ExtendedString HYDROData_Tool::toExtString( const QString& theStr )
271 {
272   TCollection_ExtendedString aRes;
273   if( !theStr.isEmpty() )
274   {
275           Standard_ExtString extStr = new Standard_ExtCharacter[ ( theStr.length() + 1 ) * 2 ];
276           memcpy( (void*)extStr, theStr.unicode(), theStr.length() * 2 );
277           ((short*)extStr)[theStr.length()] = '\0';
278     aRes = TCollection_ExtendedString( extStr );
279           delete [] extStr;
280   }
281   return aRes;
282 }
283
284 QString HYDROData_Tool::toQString( const TCollection_ExtendedString& theStr )
285 {
286   return QString( (QChar*)theStr.ToExtString(), theStr.Length() );
287 }
288
289 Quantity_Color HYDROData_Tool::toOccColor( const QColor& theColor )
290 {
291   double r = theColor.red() / 255.0;
292   double g = theColor.green() / 255.0;
293   double b = theColor.blue() / 255.0;
294
295   return Quantity_Color( r, g, b, Quantity_TOC_RGB );
296 }
297
298 QColor HYDROData_Tool::toQtColor( const Quantity_Color& theColor )
299 {
300   int r = 255 * theColor.Red();
301   int g = 255 * theColor.Green();
302   int b = 255 * theColor.Blue();
303   return QColor( r, g, b );
304 }
305
306 bool HYDROData_Tool::IsNan( double theValue )
307 {
308 #ifdef WIN32
309   return _isnan( theValue );
310 #else
311   return isnan( theValue );
312 #endif
313 }
314
315 bool HYDROData_Tool::IsInf( double theValue )
316 {
317 #ifdef WIN32
318   return (!_finite( theValue  ) );
319 #else
320   return isinf( theValue );
321 #endif  
322 }
323
324 static void MakeShellG(const NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher>& FG,
325   TopoDS_Shape& outSh)
326 {
327   BRep_Builder bb;
328   NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher>::Iterator itFG(FG);
329   if (FG.Extent() > 1)
330   {
331     //face nb > 1 => make shell
332     TopoDS_Shell outShell;
333     bb.MakeShell(outShell);
334     for (;itFG.More();itFG.Next())
335       bb.Add(outShell, itFG.Value());
336     outSh = outShell;
337   }
338   else if (FG.Extent() == 1)
339   {
340     outSh = itFG.Value(); //one face
341   }
342 }
343
344 TopoDS_Shape HYDROData_Tool::RebuildCmp(const TopoDS_Shape& in)
345 {
346   TopTools_IndexedDataMapOfShapeListOfShape mE2LF;
347   TopExp::MapShapesAndAncestors(in, TopAbs_EDGE, TopAbs_FACE, mE2LF);
348   if (mE2LF.IsEmpty())
349     return TopoDS_Shape();
350   NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher> dfm;
351   //TopExp::MapShapes(aFuseShape, TopAbs_FACE, dfm);
352   TopExp_Explorer expf(in, TopAbs_FACE);
353   for (;expf.More(); expf.Next())
354     dfm.Add(TopoDS::Face(expf.Current()));
355
356   int nbF = dfm.Extent();
357   TopExp_Explorer exp_f(in, TopAbs_FACE);
358   const TopoDS_Face& FF = TopoDS::Face(exp_f.Current());
359   NCollection_List<TopoDS_Face> CurrFS;
360   NCollection_List<TopoDS_Face> NeighFS;
361   NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher> PrF;
362   CurrFS.Append(FF);
363   NCollection_List<NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher>> GL_F;
364   NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher> OneGr;
365   bool end = false;
366   while (!end)
367   {
368     NCollection_List<TopoDS_Face>::Iterator it_currfs(CurrFS);
369     NeighFS.Clear();
370     for (;it_currfs.More();it_currfs.Next())
371     {
372       const TopoDS_Face& CF = it_currfs.Value();
373       TopExp_Explorer exp_edge(CF, TopAbs_EDGE);
374       for (;exp_edge.More();exp_edge.Next())
375       {
376         const TopoDS_Shape& CE = exp_edge.Current();
377         const TopTools_ListOfShape& lsf = mE2LF.FindFromKey(CE);
378         TopTools_ListIteratorOfListOfShape ls_it(lsf); //always one face (since all faces are planar)
379         for (;ls_it.More();ls_it.Next())
380         {
381           const TopoDS_Face& F = TopoDS::Face(ls_it.Value());
382           if (F.IsSame(CF))
383             continue;
384           if (!PrF.Contains(F))
385           {
386             OneGr.Add(F);
387             NeighFS.Append(F);
388             PrF.Add(F);
389           }
390         }
391       }
392       OneGr.Add(CF);
393       PrF.Add(CF);
394     }
395     if (NeighFS.IsEmpty())
396     {
397       GL_F.Append(OneGr);
398       OneGr.Clear();
399       dfm.Subtract(PrF);
400       if (dfm.IsEmpty())
401         end = true;
402       else
403       {
404         NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher>::Iterator itDm(dfm);
405         const TopoDS_Face& nsh = itDm.Key();
406         NeighFS.Append(nsh);
407       }
408     }
409     CurrFS = NeighFS;
410   }
411
412   TopoDS_Shape sh;
413
414   if (GL_F.Extent() > 1)
415   {
416     TopoDS_Compound cmp;
417     NCollection_List<NCollection_Map<TopoDS_Face, TopTools_ShapeMapHasher>>::Iterator itGL_F(GL_F);  
418     BRep_Builder bb;
419     bb.MakeCompound(cmp);
420     for (;itGL_F.More();itGL_F.Next())
421     {
422       MakeShellG(itGL_F.Value(), sh);
423       if (!sh.IsNull())
424         bb.Add(cmp, sh);
425     }
426     return  cmp;
427   }
428   else if (GL_F.Extent() == 1)
429   {
430     MakeShellG(GL_F.First(), sh);
431     return sh;
432   }
433   
434 }
435
436
437 std::ostream& operator<<( std::ostream& theStream, const QString& theText )
438 {
439   theStream << theText.toStdString();
440   return theStream;
441 }
442
443 std::ostream& operator<<( std::ostream& theStream, const QColor& theColor )
444 {
445   theStream << "[" << theColor.red() << ", " << theColor.green() << ", " << theColor.blue() << "]";
446   return theStream;
447 }
448
449 std::ostream& operator<<( std::ostream& theStream, const TopoDS_Shape& theShape )
450 {
451   theStream << "[" << theShape.TShape().operator->() << "]";
452   return theStream;
453 }
454
455 std::ostream& operator<<( std::ostream& theStream, const TopoDS_Face& theFace )
456 {
457   theStream << "[" << theFace.TShape().operator->() << "]";
458   return theStream;
459 }
460
461 std::ostream& operator<<( std::ostream& theStream, const gp_XY& theXY )
462 {
463   theStream << "(" << theXY.X() << "; " << theXY.Y() << ")";
464   return theStream;
465 }
466
467 bool operator == ( const gp_XY& thePoint1, const gp_XY& thePoint2 )
468 {
469   const double EPS = 1E-3;
470   return
471     fabs( thePoint1.X() - thePoint2.X() ) < EPS &&
472     fabs( thePoint1.Y() - thePoint2.Y() ) < EPS;
473
474 }