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.
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.
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
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "HYDROGUI_MeasurementToolOp.h"
21 #include "HYDROGUI_DataModel.h"
22 #include "HYDROGUI_Module.h"
24 #include <HYDROData_Object.h>
25 #include <HYDROData_IPolyline.h>
27 #include <LightApp_Application.h>
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>
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>
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>
60 HYDROGUI_MeasurementToolOp::HYDROGUI_MeasurementToolOp( HYDROGUI_Module* theModule )
61 : HYDROGUI_Operation( theModule ),
69 setName( tr( "MEASUREMENT_TOOL" ) );
72 HYDROGUI_MeasurementToolOp::~HYDROGUI_MeasurementToolOp()
78 void HYDROGUI_MeasurementToolOp::startOperation()
80 HYDROGUI_Operation::startOperation();
82 myMeasDlg = new HYDROGUI_MeasurementToolDlg( module()->getApp()->desktop() );
83 myMeasDlg->setModal( false );
84 myMeasDlg->setWindowTitle(getName());
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 ) );
92 setPreviewManager( aViewManager );
94 connect( myMeasDlg, SIGNAL( clearLine() ), this, SLOT( onClearLine() ) );
96 connect( myMeasDlg, SIGNAL( doExit() ), this, SLOT( onExit() ) );
98 OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
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*)));
106 HYDROData_Iterator anIter( doc(), KIND_POLYLINEXY );
107 QStringList aPolylineNames;
109 for ( ; anIter.More(); anIter.Next() )
111 Handle(HYDROData_PolylineXY) aPolylineObj = Handle(HYDROData_PolylineXY)::DownCast( anIter.Current() );
112 myPolyObjs.push_back(aPolylineObj);
113 aPolylineNames << aPolylineObj->GetName();
115 myMeasDlg->setPolylineNames(aPolylineNames);
118 void HYDROGUI_MeasurementToolOp::onClearLine()
122 //myPolyObjs.clear();
123 myMeasDlg->setTotalDst(0);
126 myFW = TopoDS_Wire();
129 void HYDROGUI_MeasurementToolOp::onMousePress(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
131 OCCViewer_ViewManager* aViewManager = getPreviewManager();
135 OCCViewer_ViewWindow* aViewWindow = (OCCViewer_ViewWindow*)aViewManager->getActiveView();
139 OCCViewer_ViewPort3d* aViewPort = aViewWindow->getViewPort();
143 Handle(V3d_View) aView = aViewPort->getView();
144 if ( aView.IsNull() )
147 OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
151 Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
155 gp_Pnt aPnt = CurveCreator_Utils::ConvertClickToPoint( theEvent->x(), theEvent->y(), aView );
159 if (myMeasDlg->IsLDChecked())
163 myLineMaker = new BRepLib_MakePolygon();
164 myLineMaker->Add(aPnt);
165 aRes = myLineMaker->FirstVertex();
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));
176 myMeasDlg->setTotalDst(QString::number(myDist));
179 if ( !myAISLineM.IsNull() )
181 if ( aCtx->HasOpenedContext() )
182 aCtx->CloseLocalContext();
183 aCtx->Erase( myAISLineM, Standard_False );
188 double prec = 70; //minimum precision
189 int selectInd = myMeasDlg->currentSelectedPolyline();
192 Handle(HYDROData_PolylineXY) aPolylineObj = myPolyObjs[selectInd];
193 TopoDS_Shape aShape = aPolylineObj->GetShape();
194 TopExp_Explorer exp(aShape, TopAbs_WIRE);
195 double fdist_min = RealLast();
197 BRepAdaptor_Curve minC;
199 for (;exp.More(); exp.Next())
201 TopoDS_Wire W = TopoDS::Wire(exp.Current());
204 TopExp_Explorer expW(W, TopAbs_EDGE);
207 TopoDS_Edge E = TopoDS::Edge(expW.Current());
210 E = BRepAlgo::ConcatenateWireC0(W);
211 BRepAdaptor_Curve Ad(E);
212 Handle(Geom_BSplineCurve) aBsp = Ad.Curve().BSpline();
213 std::vector<double> params;
214 double Fp = Ad.FirstParameter();
215 double Lp = Ad.LastParameter();
216 params.push_back(Fp);
217 params.push_back(Lp);
220 TColStd_Array1OfReal aKnots = aBsp->Knots();
221 for (int i = 1; i <= aKnots.Size(); i++)
223 if (aKnots(i) > Fp && aKnots(i) < Lp)
224 params.push_back(aKnots(i));
227 //in some cases, extrema gives inaccurate result ->
228 //split bspline by knot params and try to find minimum distance
230 std::sort(params.begin(), params.end());
231 for (int i = 0; i < params.size() - 1; i++ )
233 //Extrema_ExtPC extrema(aPnt, Ad, params[i], params[i+1]);
234 GeomAPI_ProjectPointOnCurve aProj; //extrema wrapper
235 aProj.Init (aPnt, Ad.Curve().Curve(), params[i], params[i+1]);
236 if (aProj.NbPoints() > 0)
238 double fdist = aProj.LowerDistance();
239 gp_Pnt aFP = aProj.NearestPoint();
240 int x1=-1, y1=-1, x2=-1, y2=-1;
241 CurveCreator_Utils::ConvertPointToClick(aPnt, aView, x1, y1);
242 CurveCreator_Utils::ConvertPointToClick(aFP, aView, x2, y2);
243 gp_Pnt2d pp1((double)x1, (double)y1);
244 gp_Pnt2d pp2((double)x2, (double)y2);
246 aView->Window()->Size(aWinSX, aWinSY);
247 double pd = pp1.Distance(pp2);
248 double WinDiagDist = sqrt ((double)aWinSX*(double)aWinSX + (double)aWinSY*(double)aWinSY);
249 if (fdist <= prec || pd / WinDiagDist < 0.08)
251 if (fdist < fdist_min)
255 minU = aProj.LowerDistanceParameter();
263 if (!minWire.IsNull())
269 aRes = BRepLib_MakeVertex(aPnt);
273 if (myFW.IsSame(minWire))
275 //calc distance on current curve
276 double LenAlongCurv = GCPnts_AbscissaPoint::Length(minC, myFu, minU);
277 myFW = TopoDS_Wire();
278 if (!BRep_Tool::IsClosed(minWire))
280 aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
281 myMeasDlg->setTotalDst(QString::number(LenAlongCurv));
285 double Len2 = GCPnts_AbscissaPoint::Length(minC) - LenAlongCurv;
286 if (LenAlongCurv < Len2)
287 aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
290 TopoDS_Compound aCmpEd;
292 aB.MakeCompound(aCmpEd);
293 aB.Add(aCmpEd, BRepLib_MakeEdge(minC.Curve().Curve(), minC.FirstParameter(), Min(myFu, minU)));
294 aB.Add(aCmpEd, BRepLib_MakeEdge(minC.Curve().Curve(), Max(myFu, minU), minC.LastParameter()));
297 myMeasDlg->setTotalDst(QString::number(LenAlongCurv) + ", " + QString::number(Len2));
307 aCtx->Erase( myAISLineM, Standard_False );
309 myAISLineM = new AIS_Shape( aRes );
311 myAISLineM->SetColor( Quantity_NOC_ORANGE );
312 //Handle(Prs3d_Drawer) aHA = myAISLineM->HilightAttributes();
314 myAISLineM->SetWidth( 3 );
315 //Handle(Prs3d_PointAspect) anAspect = mySplitPointPreview->Attributes()->PointAspect();
316 //anAspect->SetScale(2.0);
317 //anAspect->SetTypeOfMarker(Aspect_TOM_RING1);
318 //anAspect->SetColor(Quantity_NOC_BLACK);
319 //mySplitPointPreview->Attributes()->SetPointAspect( anAspect );
321 aCtx->SetZLayer(myAISLineM, Graphic3d_ZLayerId_Topmost);
323 if ( aCtx->HasOpenedContext() )
324 aCtx->CloseLocalContext();
325 aCtx->Display( myAISLineM, Standard_False );
326 aCtx->UpdateCurrentViewer();
329 void HYDROGUI_MeasurementToolOp::eraseLine()
331 OCCViewer_ViewManager* aViewManager = getPreviewManager();
334 if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() )
336 if ( !myAISLineM.IsNull() )
338 Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
339 if ( !aCtx.IsNull() )
341 if ( aCtx->HasOpenedContext() )
342 aCtx->CloseLocalContext();
343 aCtx->Erase( myAISLineM, Standard_False );
345 myAISLineM.Nullify();
346 aCtx->UpdateCurrentViewer();
352 void HYDROGUI_MeasurementToolOp::abortOperation()
354 if (!myMeasDlg->GetExitFlag())
358 void HYDROGUI_MeasurementToolOp::onExit()
361 OCCViewer_ViewManager* aViewManager = getPreviewManager();
362 OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
364 if (aViewManager && aViewer)
366 disconnect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
367 this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
369 connect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
370 aViewManager->getOCCViewer(), SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
376 this->blockSignals(true);
377 HYDROGUI_Operation::abort();
378 this->blockSignals(false);