Salome HOME
OCC functionality moving out from the widget
[modules/hydro.git] / src / HYDROCurveCreator / CurveCreator_Utils.cxx
1 // Copyright (C) 2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "CurveCreator_Utils.h"
21
22 #include <GEOMUtils.hxx>
23
24 #include <gp_Pln.hxx>
25
26 #include <TopoDS.hxx>
27 #include <TopoDS_Vertex.hxx>
28 #include <TopoDS_Wire.hxx>
29 #include <TopoDS_Edge.hxx>
30
31 #include <AIS_ListOfInteractive.hxx>
32 #include <AIS_ListIteratorOfListOfInteractive.hxx>
33 #include <AIS_Shape.hxx>
34 #include <AIS_Point.hxx>
35 #include <AIS_Line.hxx>
36 #include <AIS_Trihedron.hxx>
37
38 #include <Geom_Point.hxx>
39 #include <Geom_BSplineCurve.hxx>
40 #include <Geom_Line.hxx>
41
42 #include <TopExp_Explorer.hxx>
43 #include <BRep_Tool.hxx>
44 #include <GeomAPI_ProjectPointOnCurve.hxx>
45 #include <SelectMgr_EntityOwner.hxx>
46
47 #include <ProjLib.hxx>
48 #include <ElSLib.hxx>
49
50 const double LOCAL_SELECTION_TOLERANCE = 0.0001;
51 const int    SCENE_PIXEL_TOLERANCE = 10;
52
53 //=======================================================================
54 // function : ConvertClickToPoint()
55 // purpose  : Returns the point clicked in 3D view
56 //=======================================================================
57 void CurveCreator_Utils::ConvertPointToClick( const gp_Pnt& thePoint,
58                                               Handle(V3d_View) theView,
59                                               int& x, int& y )
60 {
61   theView->Convert(thePoint.X(), thePoint.Y(), thePoint.Z(), x, y );
62 }
63
64
65 //=======================================================================
66 // function : ConvertClickToPoint()
67 // purpose  : Returns the point clicked in 3D view
68 //=======================================================================
69 gp_Pnt CurveCreator_Utils::ConvertClickToPoint( int x, int y, Handle(V3d_View) aView )
70 {
71   return GEOMUtils::ConvertClickToPoint( x, y, aView );
72 }
73
74 std::list<float> CurveCreator_Utils::getSelectedPoints( Handle(AIS_InteractiveContext) theContext )
75 {
76   std::list<float> aSelectedPoints;
77
78   gp_Pnt aPnt;
79   for ( theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected() ) {
80     TopoDS_Vertex aVertex;
81     TopoDS_Shape aShape = theContext->SelectedShape();
82     if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX )
83       aVertex = TopoDS::Vertex( theContext->SelectedShape() );
84     else {
85       Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
86       if ( !anOwner.IsNull() ) {
87         Handle(AIS_InteractiveObject) anAIS = Handle(AIS_InteractiveObject)::DownCast( anOwner->Selectable() );
88         if ( !anAIS.IsNull() ) {
89           Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast( anAIS);
90           if ( !aPoint.IsNull() )
91             aVertex = TopoDS::Vertex( aPoint->Vertex() );
92         }
93         if ( aVertex.IsNull() ) {
94           // the following happens if there are no points in the current curve, there is only a shape
95           /*Handle(StdSelect_BRepOwner) aBrepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
96           if ( aBrepOwner.IsNull() )
97             continue;
98           if ( aBrepOwner->HasShape() ) {
99             const TopoDS_Shape& aShape = aBrepOwner->Shape();
100             if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX )
101             {
102               aVertex = TopoDS::Vertex( aShape );
103             }
104           }*/
105         }
106       }
107     }
108     if ( aVertex.IsNull() )
109       continue;
110     aPnt = BRep_Tool::Pnt( aVertex );
111     aSelectedPoints.push_back( aPnt.X() );
112     aSelectedPoints.push_back( aPnt.Y() );
113     aSelectedPoints.push_back( aPnt.Z() );
114   }
115
116   return aSelectedPoints;
117 }
118 //=======================================================================
119 // function : setLocalPointContext
120 // purpose  : Open/close the viewer local context
121 //=======================================================================
122 //#define USE_COMPOUND
123 void CurveCreator_Utils::setLocalPointContext(
124                                               Handle(AIS_InteractiveContext) theContext,
125                                               const bool theOpen )
126 {
127 #ifdef USE_COMPOUND
128   return;
129 #endif
130   if ( !theContext )
131     return;
132
133   if ( theOpen ) {
134     // Open local context if there is no one
135     if ( !theContext->HasOpenedContext() ) {
136       theContext->ClearCurrents( false );
137       theContext->OpenLocalContext( false/*use displayed objects*/, true/*allow shape decomposition*/ );
138     }
139     AIS_ListOfInteractive aList;
140     theContext->DisplayedObjects( aList );
141     int aLSize = 0;
142     for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
143       aLSize++;
144
145     for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
146     {
147       Handle(AIS_InteractiveObject) anAIS = it.Value();
148       if ( !anAIS.IsNull() )
149       {
150         if ( anAIS->IsKind( STANDARD_TYPE( AIS_Shape ) ) )
151         {
152           theContext->Load( anAIS, -1/*selection mode*/, true/*allow decomposition*/ );
153           //theContext->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_WIRE ) );
154           theContext->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_VERTEX ) );
155         }
156         else if ( anAIS->DynamicType() != STANDARD_TYPE(AIS_Trihedron) )
157         {
158           theContext->Load( anAIS, -1/*selection mode*/, false/*allow decomposition*/ );
159           theContext->Activate( anAIS, TopAbs_VERTEX );
160         }
161       }
162       continue;
163     }
164   }
165   else {
166     if ( theContext->HasOpenedContext() )
167       theContext->CloseAllContexts();
168   }
169 }
170
171 bool CurveCreator_Utils::getNeighbourPoints( Handle(AIS_InteractiveContext) theContext,
172                                              Handle(V3d_View) theView,
173                                              const int theX, const int theY,
174                                              gp_Pnt& thePoint, gp_Pnt& thePoint1,
175                                              gp_Pnt& thePoint2 )
176 {
177   bool isFoundPoint = false;
178   if ( theContext.IsNull() )
179     return isFoundPoint;
180
181   for ( theContext->InitSelected(); theContext->MoreSelected() && !isFoundPoint;
182         theContext->NextSelected() ) {
183     TopoDS_Shape aTShape = theContext->SelectedShape();
184     if ( !aTShape.IsNull() && aTShape.ShapeType() == TopAbs_VERTEX )
185       continue;
186     else {
187       Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
188       if ( anOwner.IsNull() )
189         continue;
190       const TopLoc_Location& aLocation = anOwner->Location();
191       Handle(AIS_InteractiveObject) anAIS =
192                         Handle(AIS_InteractiveObject)::DownCast( anOwner->Selectable() );
193       isFoundPoint = CurveCreator_Utils::pointOnObject( theView, anAIS, theX, theY, thePoint,
194                                                         thePoint1, thePoint2 );
195     }
196   }
197   return isFoundPoint;
198 }
199
200 bool CurveCreator_Utils::pointOnObject( Handle(V3d_View) theView,
201                                         Handle(AIS_InteractiveObject) theObject,
202                                         const int theX, const int theY,
203                                         gp_Pnt& thePoint,
204                                         gp_Pnt& thePoint1, gp_Pnt& thePoint2 )
205 {
206   bool isFound = false;
207
208   if ( theObject.IsNull() || theView.IsNull() )
209     return isFound;
210
211   gp_Pnt aPoint;
212   Standard_Real aParameter;
213   gp_Pnt aPnt1, aPnt2;
214   Handle(AIS_Line) aLine = Handle(AIS_Line)::DownCast( theObject );
215   if ( !aLine.IsNull() ) {
216     const Handle(Geom_Line) aGLine = aLine->Line();
217     isFound = hasProjectPointOnCurve( theView, theX, theY, aGLine, aParameter );
218     if ( isFound ) {
219       aPoint = aGLine->Value( aParameter );
220
221       Handle(Geom_Point) aPStart;
222       Handle(Geom_Point) aPEnd;
223       aLine->Points( aPStart, aPEnd );
224       aPnt1 = aPStart->Pnt();
225       aPnt2 = aPEnd->Pnt();
226
227       // in case of Geom line a projection is performed to the infinite line,
228       // so it is necessary to bound it by the line size
229       Bnd_Box aLineBox;
230       aLineBox.Set( aPnt1, gp_Vec( aPnt1, aPnt2 ) );
231       isFound = !aLineBox.IsOut( aPoint );
232     }
233   }
234   else {
235     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast( theObject );
236     if ( !aShape.IsNull() ) {
237       const TopoDS_Wire& aWire = TopoDS::Wire( aShape->Shape() );
238       if ( !aWire.IsNull() ) {
239         TopExp_Explorer anExp( aWire, TopAbs_EDGE );
240         for ( ; anExp.More(); anExp.Next())
241         {
242           const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
243           if ( !anEdge.IsNull() ) {
244             Standard_Real aFirst, aLast;
245             Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst, aLast );
246
247             if ( aCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) ) {
248               Handle(Geom_BSplineCurve) aBSplineCurve = Handle(Geom_BSplineCurve)::DownCast( aCurve );
249               if ( !aBSplineCurve.IsNull() ) {
250                 isFound = hasProjectPointOnCurve( theView, theX, theY, aCurve, aParameter );
251                 if ( isFound ) {
252                   aPoint = aBSplineCurve->Value( aParameter );
253                   Standard_Integer anI1, anI2;
254                   aBSplineCurve->LocateU( aParameter, LOCAL_SELECTION_TOLERANCE, anI1, anI2 );
255
256                   aPnt1 = aBSplineCurve->Value( aBSplineCurve->Knot( anI1 ) );
257                   aPnt2 = aBSplineCurve->Value( aBSplineCurve->Knot( anI2 ) );
258                 }
259               }
260             }
261           }
262         }
263       }
264     }
265   }
266   if ( isFound ) {
267     thePoint = aPoint;
268     thePoint1 = aPnt1;
269     thePoint2 = aPnt2;
270   }
271   return isFound;
272 }
273
274 bool CurveCreator_Utils::hasProjectPointOnCurve( Handle(V3d_View) theView,
275                                                  const int theX, const int theY,
276                                                  const Handle(Geom_Curve)& theCurve,
277                                                  Standard_Real& theParameter )
278 {
279   bool isFound = false;
280   if ( theView.IsNull() )
281     return isFound;
282
283   gp_Pnt aPoint = CurveCreator_Utils::ConvertClickToPoint( theX, theY, theView );
284
285   GeomAPI_ProjectPointOnCurve aProj( aPoint, theCurve );
286   Standard_Integer aNbPoint = aProj.NbPoints();
287   if (aNbPoint > 0) {
288     for (Standard_Integer j = 1; j <= aNbPoint && !isFound; j++) {
289       gp_Pnt aNewPoint = aProj.Point( j );
290       theParameter = aProj.Parameter( j );
291
292       int aX, anY;
293       CurveCreator_Utils::ConvertPointToClick( aNewPoint, theView, aX, anY );
294
295       int aXDelta = abs( aX - theX );
296       int anYDelta = abs( anY - theY );
297       isFound = aXDelta < SCENE_PIXEL_TOLERANCE && anYDelta < SCENE_PIXEL_TOLERANCE;
298     }
299   }
300   return isFound;
301 }