Salome HOME
cleaning some comments
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_MeasurementToolOp.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 "HYDROGUI_MeasurementToolOp.h"
20
21 #include "HYDROGUI_DataModel.h"
22 #include "HYDROGUI_Module.h"
23
24 #include <HYDROData_Object.h>
25 #include <HYDROData_IPolyline.h>
26
27 #include <LightApp_Application.h>
28
29 #include <SUIT_Desktop.h>
30 #include <HYDROGUI_Tool2.h>
31 #include <HYDROGUI_MeasurementToolDlg.h>
32 #include <OCCViewer_ViewModel.h>
33 #include <OCCViewer_ViewManager.h>
34 #include <OCCViewer_ViewPort3d.h>
35 #include <OCCViewer_ViewWindow.h>
36 #include <BRep_Builder.hxx>
37 #include <BRepBuilderAPI_MakeVertex.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Compound.hxx>
40 #include <AIS_Shape.hxx>
41 #include <CurveCreator_Utils.hxx>
42 #include <QMouseEvent>
43 #include <TopExp.hxx>
44 #include <HYDROData_Iterator.h>
45 #include <HYDROData_PolylineXY.h>
46 #include <GCPnts_AbscissaPoint.hxx>
47 #include <TopExp_Explorer.hxx>
48 #include <BRepAdaptor_Curve.hxx>
49 #include <TopoDS.hxx>
50 #include <vector>
51 #include <utility>
52 #include <Prs3d_Drawer.hxx>
53 #include <BRepAlgo.hxx>
54 #include <BRepAdaptor_Curve.hxx>
55 #include <BRepLib_MakeEdge.hxx>
56 #include <GeomAPI_ProjectPointOnCurve.hxx>
57 #include <BRepLib_MakePolygon.hxx>
58
59
60 HYDROGUI_MeasurementToolOp::HYDROGUI_MeasurementToolOp( HYDROGUI_Module* theModule )
61   : HYDROGUI_Operation( theModule ),
62   myMeasDlg(0),
63   myLineMaker(NULL),
64   myAISLineM(NULL),
65   myDist(0),
66  // myFAd(NULL),
67   myFu(0)
68 {
69   setName( tr( "MEASUREMENT_TOOL" ) );
70 }
71
72 HYDROGUI_MeasurementToolOp::~HYDROGUI_MeasurementToolOp()
73 {
74   if (myLineMaker)
75     delete myLineMaker;
76 }
77
78 void HYDROGUI_MeasurementToolOp::startOperation()
79 {
80   HYDROGUI_Operation::startOperation();
81
82   myMeasDlg = new HYDROGUI_MeasurementToolDlg( module()->getApp()->desktop() );
83   myMeasDlg->setModal( false );
84   myMeasDlg->setWindowTitle(getName());
85   myMeasDlg->show();
86
87   //Tool: draw a distance line
88   LightApp_Application* anApp = module()->getApp();
89   OCCViewer_ViewManager* aViewManager =
90     dynamic_cast<OCCViewer_ViewManager*>( anApp->getViewManager( OCCViewer_Viewer::Type(), true ) );
91
92   setPreviewManager( aViewManager );
93
94   connect( myMeasDlg, SIGNAL( clearLine() ), this, SLOT( onClearLine() ) );
95
96   connect( myMeasDlg, SIGNAL( doExit() ), this, SLOT( onExit() ) );
97
98   OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
99
100   disconnect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
101     aViewer, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
102   connect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
103     this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
104
105   //polyline names
106   HYDROData_Iterator anIter( doc(), KIND_POLYLINEXY );
107   QStringList aPolylineNames;
108   myPolyObjs.clear();
109   for ( ; anIter.More(); anIter.Next() )
110   {
111     Handle(HYDROData_PolylineXY) aPolylineObj = Handle(HYDROData_PolylineXY)::DownCast( anIter.Current() );
112     myPolyObjs.push_back(aPolylineObj);
113     aPolylineNames << aPolylineObj->GetName();
114   }
115   myMeasDlg->setPolylineNames(aPolylineNames);
116 }
117
118 void HYDROGUI_MeasurementToolOp::onClearLine()
119 {
120   eraseLine();
121   myDist = 0;
122   //myPolyObjs.clear();
123   myMeasDlg->setTotalDst(0);
124   delete myLineMaker;
125   myLineMaker = NULL;
126   myFW = TopoDS_Wire();
127 }
128
129 void HYDROGUI_MeasurementToolOp::onMousePress(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
130 {
131   OCCViewer_ViewManager* aViewManager = getPreviewManager();
132   if ( !aViewManager )
133     return;
134
135   OCCViewer_ViewWindow* aViewWindow = (OCCViewer_ViewWindow*)aViewManager->getActiveView();
136   if ( !aViewWindow )
137     return;
138
139   OCCViewer_ViewPort3d* aViewPort = aViewWindow->getViewPort();
140   if ( !aViewPort )
141     return;
142
143   Handle(V3d_View) aView = aViewPort->getView();
144   if ( aView.IsNull() )
145     return;
146
147   OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
148   if ( !aViewer )
149     return;
150
151   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
152   if ( aCtx.IsNull() )
153     return;
154
155   gp_Pnt aPnt = CurveCreator_Utils::ConvertClickToPoint( theEvent->x(), theEvent->y(), aView );
156
157   TopoDS_Shape aRes;
158
159   if (myMeasDlg->IsLDChecked())
160   {
161     if (!myLineMaker)
162     {
163       myLineMaker = new BRepLib_MakePolygon();
164       myLineMaker->Add(aPnt);
165       aRes = myLineMaker->FirstVertex();
166     }
167     else
168     {
169       myLineMaker->Add(aPnt);
170       aRes = myLineMaker->Shape();
171       const TopoDS_Edge& aLE = myLineMaker->Edge();
172       TopoDS_Vertex aFV = TopExp::FirstVertex(aLE, true);
173       TopoDS_Vertex aLV = TopExp::LastVertex(aLE, true);
174       double aNDist = BRep_Tool::Pnt(aFV).Distance(BRep_Tool::Pnt(aLV));
175       myDist += aNDist;
176       myMeasDlg->setTotalDst(QString::number(myDist));
177     }
178
179     if ( !myAISLineM.IsNull() )
180     {
181       aCtx->Erase( myAISLineM, Standard_False );
182     }
183   }
184   else
185   {
186     double prec = 70; //minimum precision
187     int selectInd = myMeasDlg->currentSelectedPolyline();
188     if (selectInd == -1)
189       return;
190     Handle(HYDROData_PolylineXY) aPolylineObj = myPolyObjs[selectInd];
191     TopoDS_Shape aShape = aPolylineObj->GetShape();
192     TopExp_Explorer exp(aShape, TopAbs_WIRE);
193     double fdist_min = RealLast();
194     TopoDS_Wire minWire;
195     BRepAdaptor_Curve minC;
196     double minU;
197     for (;exp.More(); exp.Next())
198     {
199       TopoDS_Wire W = TopoDS::Wire(exp.Current());
200       if (W.IsNull())
201         continue;
202       TopExp_Explorer expW(W, TopAbs_EDGE);
203       if (!expW.More())
204         continue;
205       TopoDS_Edge E = TopoDS::Edge(expW.Current());
206       expW.Next();
207       if (expW.More())
208         E = BRepAlgo::ConcatenateWireC0(W);
209       BRepAdaptor_Curve Ad(E);
210       Handle(Geom_BSplineCurve) aBsp = Ad.Curve().BSpline();
211       std::vector<double> params;
212       double Fp = Ad.FirstParameter();
213       double Lp = Ad.LastParameter();
214       params.push_back(Fp);
215       params.push_back(Lp);
216       if (!aBsp.IsNull())
217       {
218         TColStd_Array1OfReal aKnots = aBsp->Knots();
219         for (int i = 1; i <= aKnots.Size(); i++)
220         {
221           if (aKnots(i) > Fp && aKnots(i) < Lp)
222             params.push_back(aKnots(i));
223         }
224       }
225       //in some cases, extrema gives inaccurate result ->
226       //split bspline by knot params and try to find minimum distance
227       //on each interval
228       std::sort(params.begin(), params.end());
229       for (int i = 0; i < params.size() - 1; i++ )
230       {
231         //Extrema_ExtPC extrema(aPnt, Ad, params[i], params[i+1]);
232         GeomAPI_ProjectPointOnCurve aProj; //extrema wrapper
233         aProj.Init (aPnt, Ad.Curve().Curve(), params[i], params[i+1]);
234         if (aProj.NbPoints() > 0)
235         {
236           double fdist = aProj.LowerDistance();
237           gp_Pnt aFP = aProj.NearestPoint();
238           int x1=-1, y1=-1, x2=-1, y2=-1;
239           CurveCreator_Utils::ConvertPointToClick(aPnt, aView, x1, y1);
240           CurveCreator_Utils::ConvertPointToClick(aFP, aView, x2, y2);
241           gp_Pnt2d pp1((double)x1, (double)y1);
242           gp_Pnt2d pp2((double)x2, (double)y2);
243           int aWinSX, aWinSY;
244           aView->Window()->Size(aWinSX, aWinSY);
245           double pd = pp1.Distance(pp2);
246           double WinDiagDist = sqrt ((double)aWinSX*(double)aWinSX + (double)aWinSY*(double)aWinSY);
247           if (fdist <= prec || pd / WinDiagDist < 0.08)
248           {
249             if (fdist < fdist_min)
250             {
251               fdist_min = fdist;
252               minWire = W;
253               minU = aProj.LowerDistanceParameter();
254               minC.Initialize(E);
255             }
256           }
257         }
258       }
259     }
260     //
261     if (!minWire.IsNull())
262     {
263       if (myFW.IsNull())
264       {
265         myFu = minU;
266         myFW = minWire;
267         aRes = BRepLib_MakeVertex(aPnt);
268       }
269       else
270       {
271         if (myFW.IsSame(minWire))
272         {
273           //calc distance on current curve
274           double LenAlongCurv = GCPnts_AbscissaPoint::Length(minC, myFu, minU);
275           myFW = TopoDS_Wire();
276           if (!BRep_Tool::IsClosed(minWire))
277           {
278             aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
279             myMeasDlg->setTotalDst(QString::number(LenAlongCurv));
280           }
281           else
282           {
283             double Len2 = GCPnts_AbscissaPoint::Length(minC) - LenAlongCurv;
284             if (LenAlongCurv < Len2)
285               aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
286             else
287             {
288               TopoDS_Compound aCmpEd;
289               BRep_Builder aB;
290               aB.MakeCompound(aCmpEd);
291               aB.Add(aCmpEd, BRepLib_MakeEdge(minC.Curve().Curve(), minC.FirstParameter(), Min(myFu, minU)));
292               aB.Add(aCmpEd, BRepLib_MakeEdge(minC.Curve().Curve(), Max(myFu, minU), minC.LastParameter()));
293               aRes = aCmpEd;
294             }
295             myMeasDlg->setTotalDst(QString::number(LenAlongCurv) + "; " + QString::number(Len2));
296           }
297         }
298       }
299     }
300   }
301
302   if (aRes.IsNull())
303     return;
304
305   aCtx->Erase( myAISLineM, Standard_False );
306
307   myAISLineM = new AIS_Shape( aRes );
308
309   myAISLineM->SetColor( Quantity_NOC_ORANGE );
310   //Handle(Prs3d_Drawer) aHA = myAISLineM->HilightAttributes();
311
312   myAISLineM->SetWidth( 3 );
313   //Handle(Prs3d_PointAspect) anAspect = mySplitPointPreview->Attributes()->PointAspect();
314   //anAspect->SetScale(2.0);
315   //anAspect->SetTypeOfMarker(Aspect_TOM_RING1);
316   //anAspect->SetColor(Quantity_NOC_BLACK);
317   //mySplitPointPreview->Attributes()->SetPointAspect( anAspect );
318
319   aCtx->SetZLayer(myAISLineM, Graphic3d_ZLayerId_Topmost);
320
321   aCtx->Display( myAISLineM, Standard_False );
322   aCtx->UpdateCurrentViewer();
323 }
324
325 void HYDROGUI_MeasurementToolOp::eraseLine()
326 {
327   OCCViewer_ViewManager* aViewManager = getPreviewManager();
328   if ( aViewManager )
329   {
330     if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() )
331     {
332       if ( !myAISLineM.IsNull() )
333       {
334         Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
335         if ( !aCtx.IsNull() )
336         {
337           aCtx->Erase( myAISLineM, Standard_False );
338         }
339         myAISLineM.Nullify();
340         aCtx->UpdateCurrentViewer();
341       }
342     }
343   }
344 }
345
346 void HYDROGUI_MeasurementToolOp::abortOperation()
347 {
348   if (!myMeasDlg->GetExitFlag())
349     myMeasDlg->done(0);
350 }
351
352 void HYDROGUI_MeasurementToolOp::onExit()
353 {
354   onClearLine();
355   OCCViewer_ViewManager* aViewManager = getPreviewManager();
356   OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
357
358   if (aViewManager && aViewer)
359   {
360     disconnect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
361       this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
362
363     connect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
364       aViewManager->getOCCViewer(), SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
365   }
366
367   if (myLineMaker)
368     delete myLineMaker;
369
370   this->blockSignals(true);
371   HYDROGUI_Operation::abort();
372   this->blockSignals(false);
373 }
374
375
376
377
378