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 aCtx->Erase( myAISLineM, Standard_False );
186 double prec = 70; //minimum precision
187 int selectInd = myMeasDlg->currentSelectedPolyline();
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();
195 BRepAdaptor_Curve minC;
197 for (;exp.More(); exp.Next())
199 TopoDS_Wire W = TopoDS::Wire(exp.Current());
202 TopExp_Explorer expW(W, TopAbs_EDGE);
205 TopoDS_Edge E = TopoDS::Edge(expW.Current());
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);
218 TColStd_Array1OfReal aKnots = aBsp->Knots();
219 for (int i = 1; i <= aKnots.Size(); i++)
221 if (aKnots(i) > Fp && aKnots(i) < Lp)
222 params.push_back(aKnots(i));
225 //in some cases, extrema gives inaccurate result ->
226 //split bspline by knot params and try to find minimum distance
228 std::sort(params.begin(), params.end());
229 for (int i = 0; i < params.size() - 1; i++ )
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)
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);
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)
249 if (fdist < fdist_min)
253 minU = aProj.LowerDistanceParameter();
261 if (!minWire.IsNull())
267 aRes = BRepLib_MakeVertex(aPnt);
271 if (myFW.IsSame(minWire))
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))
278 aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
279 myMeasDlg->setTotalDst(QString::number(LenAlongCurv));
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));
288 TopoDS_Compound aCmpEd;
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()));
295 myMeasDlg->setTotalDst(QString::number(LenAlongCurv) + "; " + QString::number(Len2));
305 aCtx->Erase( myAISLineM, Standard_False );
307 myAISLineM = new AIS_Shape( aRes );
309 myAISLineM->SetColor( Quantity_NOC_ORANGE );
310 //Handle(Prs3d_Drawer) aHA = myAISLineM->HilightAttributes();
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 );
319 aCtx->SetZLayer(myAISLineM, Graphic3d_ZLayerId_Topmost);
321 aCtx->Display( myAISLineM, Standard_False );
322 aCtx->UpdateCurrentViewer();
325 void HYDROGUI_MeasurementToolOp::eraseLine()
327 OCCViewer_ViewManager* aViewManager = getPreviewManager();
330 if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() )
332 if ( !myAISLineM.IsNull() )
334 Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
335 if ( !aCtx.IsNull() )
337 aCtx->Erase( myAISLineM, Standard_False );
339 myAISLineM.Nullify();
340 aCtx->UpdateCurrentViewer();
346 void HYDROGUI_MeasurementToolOp::abortOperation()
348 if (!myMeasDlg->GetExitFlag())
352 void HYDROGUI_MeasurementToolOp::onExit()
355 OCCViewer_ViewManager* aViewManager = getPreviewManager();
356 OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
358 if (aViewManager && aViewer)
360 disconnect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
361 this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
363 connect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
364 aViewManager->getOCCViewer(), SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
370 this->blockSignals(true);
371 HYDROGUI_Operation::abort();
372 this->blockSignals(false);