]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_Tool.cxx
Salome HOME
fast algorithm of altitude computing on plane edge/wire
[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
21 #include "HYDROData_ArtificialObject.h"
22 #include "HYDROData_Image.h"
23 #include "HYDROData_Iterator.h"
24 #include "HYDROData_NaturalObject.h"
25
26 #include <QFile>
27 #include <QStringList>
28 #include <QTextStream>
29
30 #include <limits>
31 #include <gp_Pnt.hxx>
32 #include <gp_Pln.hxx>
33 #include <ElSLib.hxx>
34 #include <TopAbs_State.hxx>
35 #include <BRepAdaptor_Surface.hxx>
36 #include <BRepTopAdaptor_FClass2d.hxx>
37 #include <BRep_Tool.hxx>
38 #include <Geom_Curve.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_Wire.hxx>
41 #include <TopExp_Explorer.hxx>
42
43 static int aMaxNameId = std::numeric_limits<int>::max();
44
45 void HYDROData_Tool::WriteStringsToFile( QFile&             theFile,
46                                          const QStringList& theStrings,
47                                          const QString&     theSep )
48 {
49   if ( !theFile.isOpen() || theStrings.isEmpty() )
50     return;
51   
52   QString aWriteStr = theStrings.join( theSep );
53   if ( aWriteStr.isEmpty() )
54     return;
55
56   QTextStream anOutStream( &theFile );
57   anOutStream << aWriteStr << theSep << theSep;
58 }
59
60 void HYDROData_Tool::SetMustBeUpdatedObjects(
61   const Handle(HYDROData_Document)& theDoc  )
62 {
63   bool anIsChanged = true;
64
65   // iterate until there is no changes because objects on all level of dependency must be updated
66   while ( anIsChanged )
67   {
68     anIsChanged = false;
69
70     HYDROData_Iterator anIter( theDoc );
71     for ( ; anIter.More(); anIter.Next() )
72     {
73       Handle(HYDROData_Entity) anObject = anIter.Current();
74       if ( anObject.IsNull() || anObject->IsMustBeUpdated() )
75         continue;
76
77       HYDROData_SequenceOfObjects aRefSeq = anObject->GetAllReferenceObjects();
78       for ( int i = 1, n = aRefSeq.Length(); i <= n; ++i )
79       {
80         Handle(HYDROData_Entity) aRefObject = aRefSeq.Value( i );
81         if ( aRefObject.IsNull() || !aRefObject->IsMustBeUpdated() )
82           continue;
83
84         anObject->SetToUpdate( true );
85         anIsChanged = true;
86         break;
87       }
88     }
89   }
90 }
91
92 QString HYDROData_Tool::GenerateObjectName( const Handle(HYDROData_Document)& theDoc,
93                                             const QString&                    thePrefix,
94                                             const QStringList&                theUsedNames,
95                                             const bool                        theIsTryToUsePurePrefix )
96 {
97   QStringList aNamesList( theUsedNames );
98
99   // Collect all used names in the document
100   HYDROData_Iterator anIter( theDoc );
101   for( ; anIter.More(); anIter.Next() )
102   {
103     Handle(HYDROData_Entity) anObject = anIter.Current();
104     if( anObject.IsNull() )
105       continue;
106
107     QString anObjName = anObject->GetName();
108     if ( anObjName.isEmpty() )
109       continue;
110
111     aNamesList.append( anObjName );
112   }
113
114   QString aName;
115
116   if ( theIsTryToUsePurePrefix && !aNamesList.contains( thePrefix ) ) {
117     aName = thePrefix;
118   } else {
119     int anId = 1;
120     while( anId < aMaxNameId )
121     {
122       aName = QString( "%1_%2" ).arg( thePrefix ).arg( QString::number( anId++ ) );
123
124       // check that there are no other objects with the same name in the document
125       if ( !aNamesList.contains( aName ) )
126         break;
127     }
128   }
129
130   return aName;
131 }
132
133 bool HYDROData_Tool::IsGeometryObject( const Handle(HYDROData_Entity)& theObject )
134 {
135   if ( theObject.IsNull() )
136     return false;
137   
138   return theObject->IsKind( STANDARD_TYPE(HYDROData_ArtificialObject) ) ||
139          theObject->IsKind( STANDARD_TYPE(HYDROData_NaturalObject) );
140 }
141
142 void HYDROData_Tool::UpdateChildObjectName( const QString&                  theOldStr,
143                                             const QString&                  theNewStr,
144                                             const Handle(HYDROData_Entity)& theObject )
145 {
146   if ( theObject.IsNull() )
147     return;
148
149   QString anObjName = theObject->GetName();
150   if ( theOldStr.isEmpty() )
151   {
152     while ( anObjName.startsWith( '_' ) )
153       anObjName.remove( 0, 1 );
154
155     anObjName.prepend( theNewStr + "_" );
156   }
157   else if ( anObjName.startsWith( theOldStr ) )
158   {
159     anObjName.replace( 0, theOldStr.length(), theNewStr );
160   }
161   else
162     return;
163
164   theObject->SetName( anObjName );
165 }
166
167 QString HYDROData_Tool::GenerateNameForPython( const MapOfTreatedObjects& theTreatedObjects,
168                                                const QString&             thePrefix )
169 {
170   QString aName = thePrefix;
171   if ( !theTreatedObjects.contains( aName ) )
172     return aName;
173
174   int anId = 1;
175   while( anId < aMaxNameId )
176   {
177     aName = QString( "%1_%2" ).arg( thePrefix ).arg( QString::number( anId++ ) );
178
179     // check that there are no other objects with the same name
180     if ( !theTreatedObjects.contains( aName ) )
181       break;
182   }
183
184   return aName;
185 }
186 //======================================================================================================
187 TopAbs_State HYDROData_Tool::ComputePointState( const gp_XY& theXY, const TopoDS_Face& theFace )
188 {
189   TopAbs_State aState(TopAbs_UNKNOWN);
190   if(theFace.IsNull()) return aState;  
191   Standard_Real aTol = BRep_Tool::Tolerance(theFace);
192   BRepAdaptor_Surface Ads ( theFace, Standard_False );
193   Standard_Real toluv = Min ( Ads.UResolution(aTol), Ads.VResolution(aTol) ); 
194   const gp_Pln& aPlane = Ads.Surface().Plane();
195   gp_Pnt aPnt(theXY.X(), theXY.Y(), 0.);
196   Standard_Real aU1, aV1;
197   ElSLib::Parameters(aPlane,aPnt, aU1, aV1);
198   BRepTopAdaptor_FClass2d aClassifier( theFace, toluv ); 
199   aState = aClassifier.Perform( gp_Pnt2d(aU1, aV1), Standard_False );
200   return aState;
201 }
202
203 double HYDROData_Tool::GetAltitudeForEdge( const TopoDS_Edge& theEdge,
204                                            const gp_XY& thePoint,
205                                            double theParameterTolerance,
206                                            double theSquareDistanceTolerance,
207                                            double theInvalidAltitude )
208 {
209   double aFirst, aLast;
210   Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theEdge, aFirst, aLast );
211   if( aCurve.IsNull() )
212     return theInvalidAltitude;
213
214   gp_Pnt aFirstPnt, aLastPnt;
215
216   aCurve->D0( aFirst, aFirstPnt );
217   aCurve->D0( aLast, aLastPnt );
218
219   gp_Pnt2d aFirstPnt2d( aFirstPnt.X(), aFirstPnt.Y() );
220   gp_Pnt2d aLastPnt2d( aLastPnt.X(), aLastPnt.Y() );
221
222   double aFirstDist = 0;
223   double aLastDist = aFirstPnt2d.SquareDistance( thePoint );
224   double aNecDist = aFirstPnt2d.SquareDistance( thePoint );
225
226   while( fabs( aLast - aFirst ) > theParameterTolerance )
227   {
228     double aMid = ( aFirst + aLast ) / 2;
229     gp_Pnt aMidPnt;
230     aCurve->D0( aMid, aMidPnt );
231     double aDist = aFirstPnt2d.SquareDistance( gp_Pnt2d( aMidPnt.X(), aMidPnt.Y() ) );
232
233     if( aDist > aNecDist )
234       aFirst = aMid;
235     else
236       aLast = aMid;
237   }
238
239   double aMid = ( aFirst + aLast ) / 2;
240   gp_Pnt aMidPnt;
241   aCurve->D0( aMid, aMidPnt );
242
243   gp_Pnt2d aMidPnt2d( aMidPnt.X(), aMidPnt.Y() );
244   if( aMidPnt2d.SquareDistance( thePoint ) < theSquareDistanceTolerance )
245     return aMidPnt.Z();
246   else
247     return theInvalidAltitude;
248 }
249
250 double HYDROData_Tool::GetAltitudeForWire( const TopoDS_Wire& theWire,
251                                            const gp_XY& thePoint,
252                                            double theParameterTolerance,
253                                            double theSquareDistanceTolerance,
254                                            double theInvalidAltitude )
255 {
256   TopExp_Explorer anExp( theWire, TopAbs_EDGE );
257   for( ; anExp.More(); anExp.Next() )
258   {
259     double anAltitude = GetAltitudeForEdge( TopoDS::Edge( anExp.Current() ), thePoint,
260       theParameterTolerance, theSquareDistanceTolerance, theInvalidAltitude );
261     if( anAltitude != theInvalidAltitude )
262       return anAltitude;
263   }
264   return theInvalidAltitude;
265 }