Salome HOME
404e19aa44a688de5ada8e1e5d67d511cfbc3d06
[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 <TopExp_Explorer.hxx>
37 #include <TopoDS.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Wire.hxx>
41
42 static int aMaxNameId = std::numeric_limits<int>::max();
43
44 void HYDROData_Tool::WriteStringsToFile( QFile&             theFile,
45                                          const QStringList& theStrings,
46                                          const QString&     theSep )
47 {
48   if ( !theFile.isOpen() || theStrings.isEmpty() )
49     return;
50   
51   QString aWriteStr = theStrings.join( theSep );
52   if ( aWriteStr.isEmpty() )
53     return;
54
55   QTextStream anOutStream( &theFile );
56   anOutStream << aWriteStr << theSep << theSep;
57 }
58
59 void HYDROData_Tool::SetMustBeUpdatedObjects(
60   const Handle(HYDROData_Document)& theDoc  )
61 {
62   bool anIsChanged = true;
63
64   // iterate until there is no changes because objects on all level of dependency must be updated
65   while ( anIsChanged )
66   {
67     anIsChanged = false;
68
69     HYDROData_Iterator anIter( theDoc );
70     for ( ; anIter.More(); anIter.Next() )
71     {
72       Handle(HYDROData_Entity) anObject = anIter.Current();
73       if ( anObject.IsNull() || anObject->IsMustBeUpdated() )
74         continue;
75
76       HYDROData_SequenceOfObjects aRefSeq = anObject->GetAllReferenceObjects();
77       for ( int i = 1, n = aRefSeq.Length(); i <= n; ++i )
78       {
79         Handle(HYDROData_Entity) aRefObject = aRefSeq.Value( i );
80         if ( aRefObject.IsNull() || !aRefObject->IsMustBeUpdated() )
81           continue;
82
83         anObject->SetToUpdate( true );
84         anIsChanged = true;
85         break;
86       }
87     }
88   }
89 }
90
91 QString HYDROData_Tool::GenerateObjectName( const Handle(HYDROData_Document)& theDoc,
92                                             const QString&                    thePrefix,
93                                             const QStringList&                theUsedNames,
94                                             const bool                        theIsTryToUsePurePrefix )
95 {
96   QStringList aNamesList( theUsedNames );
97
98   // Collect all used names in the document
99   HYDROData_Iterator anIter( theDoc );
100   for( ; anIter.More(); anIter.Next() )
101   {
102     Handle(HYDROData_Entity) anObject = anIter.Current();
103     if( anObject.IsNull() )
104       continue;
105
106     QString anObjName = anObject->GetName();
107     if ( anObjName.isEmpty() )
108       continue;
109
110     aNamesList.append( anObjName );
111   }
112
113   QString aName;
114
115   if ( theIsTryToUsePurePrefix && !aNamesList.contains( thePrefix ) ) {
116     aName = thePrefix;
117   } else {
118     int anId = 1;
119     while( anId < aMaxNameId )
120     {
121       aName = QString( "%1_%2" ).arg( thePrefix ).arg( QString::number( anId++ ) );
122
123       // check that there are no other objects with the same name in the document
124       if ( !aNamesList.contains( aName ) )
125         break;
126     }
127   }
128
129   return aName;
130 }
131
132 bool HYDROData_Tool::IsGeometryObject( const Handle(HYDROData_Entity)& theObject )
133 {
134   if ( theObject.IsNull() )
135     return false;
136   
137   return theObject->IsKind( STANDARD_TYPE(HYDROData_ArtificialObject) ) ||
138          theObject->IsKind( STANDARD_TYPE(HYDROData_NaturalObject) );
139 }
140
141 void HYDROData_Tool::UpdateChildObjectName( const QString&                  theOldStr,
142                                             const QString&                  theNewStr,
143                                             const Handle(HYDROData_Entity)& theObject )
144 {
145   if ( theObject.IsNull() )
146     return;
147
148   QString anObjName = theObject->GetName();
149   if ( theOldStr.isEmpty() )
150   {
151     while ( anObjName.startsWith( '_' ) )
152       anObjName.remove( 0, 1 );
153
154     anObjName.prepend( theNewStr + "_" );
155   }
156   else if ( anObjName.startsWith( theOldStr ) )
157   {
158     anObjName.replace( 0, theOldStr.length(), theNewStr );
159   }
160   else
161     return;
162
163   theObject->SetName( anObjName );
164 }
165
166 QString HYDROData_Tool::GenerateNameForPython( const MapOfTreatedObjects& theTreatedObjects,
167                                                const QString&             thePrefix )
168 {
169   QString aName = thePrefix;
170   if ( !theTreatedObjects.contains( aName ) )
171     return aName;
172
173   int anId = 1;
174   while( anId < aMaxNameId )
175   {
176     aName = QString( "%1_%2" ).arg( thePrefix ).arg( QString::number( anId++ ) );
177
178     // check that there are no other objects with the same name
179     if ( !theTreatedObjects.contains( aName ) )
180       break;
181   }
182
183   return aName;
184 }
185 //======================================================================================================
186 TopAbs_State HYDROData_Tool::ComputePointState( const gp_XY& theXY, const TopoDS_Face& theFace )
187 {
188   TopAbs_State aState(TopAbs_UNKNOWN);
189   if(theFace.IsNull()) return aState;  
190   Standard_Real aTol = BRep_Tool::Tolerance(theFace);
191   BRepAdaptor_Surface Ads ( theFace, Standard_False );
192   Standard_Real toluv = Min ( Ads.UResolution(aTol), Ads.VResolution(aTol) ); 
193   const gp_Pln& aPlane = Ads.Surface().Plane();
194   gp_Pnt aPnt(theXY.X(), theXY.Y(), 0.);
195   Standard_Real aU1, aV1;
196   ElSLib::Parameters(aPlane,aPnt, aU1, aV1);
197   BRepTopAdaptor_FClass2d aClassifier( theFace, toluv ); 
198   aState = aClassifier.Perform( gp_Pnt2d(aU1, aV1), Standard_False );
199   return aState;
200 }
201
202 double HYDROData_Tool::GetAltitudeForEdge( const TopoDS_Edge& theEdge,
203                                            const gp_XY& thePoint,
204                                            double theParameterTolerance,
205                                            double theSquareDistanceTolerance,
206                                            double theInvalidAltitude )
207 {
208   double aFirst, aLast;
209   Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theEdge, aFirst, aLast );
210   if( aCurve.IsNull() )
211     return theInvalidAltitude;
212
213   gp_Pnt aFirstPnt, aLastPnt;
214
215   aCurve->D0( aFirst, aFirstPnt );
216   aCurve->D0( aLast, aLastPnt );
217
218   gp_Pnt2d aFirstPnt2d( aFirstPnt.X(), aFirstPnt.Y() );
219   gp_Pnt2d aLastPnt2d( aLastPnt.X(), aLastPnt.Y() );
220
221   double aFirstDist = 0;
222   double aLastDist = aFirstPnt2d.SquareDistance( aLastPnt2d );
223   double aNecDist = aFirstPnt2d.SquareDistance( thePoint );
224
225   while( fabs( aLast - aFirst ) > theParameterTolerance )
226   {
227     double aMid = ( aFirst + aLast ) / 2;
228     gp_Pnt aMidPnt;
229     aCurve->D0( aMid, aMidPnt );
230     double aDist = aFirstPnt2d.SquareDistance( gp_Pnt2d( aMidPnt.X(), aMidPnt.Y() ) );
231
232     if( aDist < aNecDist )
233       aFirst = aMid;
234     else
235       aLast = aMid;
236   }
237
238   double aMid = ( aFirst + aLast ) / 2;
239   gp_Pnt aMidPnt;
240   aCurve->D0( aMid, aMidPnt );
241
242   gp_Pnt2d aMidPnt2d( aMidPnt.X(), aMidPnt.Y() );
243   if( aMidPnt2d.SquareDistance( thePoint ) < theSquareDistanceTolerance )
244     return aMidPnt.Z();
245   else
246     return theInvalidAltitude;
247 }
248
249 double HYDROData_Tool::GetAltitudeForWire( const TopoDS_Wire& theWire,
250                                            const gp_XY& thePoint,
251                                            double theParameterTolerance,
252                                            double theSquareDistanceTolerance,
253                                            double theInvalidAltitude )
254 {
255   TopExp_Explorer anExp( theWire, TopAbs_EDGE );
256   for( ; anExp.More(); anExp.Next() )
257   {
258     double anAltitude = GetAltitudeForEdge( TopoDS::Edge( anExp.Current() ), thePoint,
259       theParameterTolerance, theSquareDistanceTolerance, theInvalidAltitude );
260     if( anAltitude != theInvalidAltitude )
261       return anAltitude;
262   }
263   return theInvalidAltitude;
264 }
265
266 TopoDS_Shape HYDROData_Tool::getFirstShapeFromGroup( const HYDROData_SequenceOfObjects& theGroups,
267                                                      const int                          theGroupId )
268 {
269   TopoDS_Shape aResShape;
270   if ( theGroupId < 1 || theGroupId > theGroups.Length() )
271     return aResShape;
272
273   Handle(HYDROData_ShapesGroup) aGroup =
274     Handle(HYDROData_ShapesGroup)::DownCast( theGroups.Value( theGroupId ) );
275   if ( aGroup.IsNull() )
276     return aResShape;
277
278   TopTools_SequenceOfShape aGroupShapes;
279   aGroup->GetShapes( aGroupShapes );
280
281   if ( !aGroupShapes.IsEmpty() )
282     aResShape = aGroupShapes.First();
283
284   return aResShape;
285 }
286
287 TCollection_ExtendedString HYDROData_Tool::toExtString( const QString& theStr )
288 {
289   TCollection_ExtendedString aRes;
290   if( !theStr.isEmpty() )
291   {
292           Standard_ExtString extStr = new Standard_ExtCharacter[ ( theStr.length() + 1 ) * 2 ];
293           memcpy( (void*)extStr, theStr.unicode(), theStr.length() * 2 );
294           ((short*)extStr)[theStr.length()] = '\0';
295     aRes = TCollection_ExtendedString( extStr );
296           delete [] extStr;
297   }
298   return aRes;
299 }
300
301 QString HYDROData_Tool::toQString( const TCollection_ExtendedString& theStr )
302 {
303   return QString( (QChar*)theStr.ToExtString(), theStr.Length() );
304 }
305
306 std::ostream& operator<<( std::ostream& theStream, const QString& theText )
307 {
308   theStream << theText.toStdString();
309   return theStream;
310 }
311
312 std::ostream& operator<<( std::ostream& theStream, const QColor& theColor )
313 {
314   theStream << "[" << theColor.red() << ", " << theColor.green() << ", " << theColor.blue() << "]";
315   return theStream;
316 }
317
318 std::ostream& operator<<( std::ostream& theStream, const TopoDS_Shape& theShape )
319 {
320   theStream << "[" << theShape.TShape().operator->() << "]";
321   return theStream;
322 }
323
324 std::ostream& operator<<( std::ostream& theStream, const TopoDS_Face& theFace )
325 {
326   theStream << "[" << theFace.TShape().operator->() << "]";
327   return theStream;
328 }
329
330