--- /dev/null
+// Copyright (C) 2014-2015 EDF-R&D
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "HYDROGUI_MeasurementToolDlg.h"
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QLineEdit>
+
+#include <OCCViewer_ViewManager.h>
+#include <OCCViewer_ViewWindow.h>
+#include <OCCViewer_ViewPort3d.h>
+#include <CurveCreator_Utils.hxx>
+#include <SUIT_ViewWindow.h>
+#include <QMouseEvent>
+#include <gp_Pnt.hxx>
+#include <QTableWidget>
+#include <QGroupBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QComboBox>
+
+#include <QRadioButton>
+#include <QStringList>
+
+
+HYDROGUI_MeasurementToolDlg::HYDROGUI_MeasurementToolDlg( QWidget* theParent )
+ : QDialog( theParent ), myExit (false)
+{
+ QFormLayout* aMLayout = new QFormLayout( this );
+
+ mySwitcherLD = new QRadioButton(tr("LINEAR_DISTANCE"));
+ QRadioButton* aSwitcherPD = new QRadioButton(tr("POLYLINE_DISTANCE"));
+
+ myPolylinesCBox = new QComboBox( this );
+
+ aMLayout->addRow(mySwitcherLD);
+ aMLayout->addRow(aSwitcherPD, myPolylinesCBox);
+
+ myTotalDst = new QLineEdit( this );
+ myTotalDst->setReadOnly(true);
+
+ aMLayout->addRow(new QLabel(tr("TOTAL_DST")), myTotalDst);
+
+ QPushButton* aClearButton = new QPushButton( tr("CLEAR") );
+
+ QPushButton* aCloseButton = new QPushButton( tr("CLOSE"), this );
+
+ QGroupBox* aPolyLenGroup = new QGroupBox(tr("POLYLINES_LENGTH"));
+ QVBoxLayout* aPolyLayout = new QVBoxLayout( aPolyLenGroup );
+
+ aMLayout->addRow(aClearButton, aCloseButton);
+ ////
+ connect( aClearButton, SIGNAL( clicked() ), this, SLOT( onClear () ) );
+ connect( aCloseButton, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( this, SIGNAL( rejected() ), this, SLOT( onExit () ) );
+ connect( mySwitcherLD, SIGNAL( toggled(bool) ), this, SLOT( onSetMode (bool) ) );
+ connect( myPolylinesCBox, SIGNAL( currentIndexChanged(int) ), this, SLOT( onClear () ) );
+
+ mySwitcherLD->setChecked(true);
+
+ setLayout(aMLayout);
+}
+
+HYDROGUI_MeasurementToolDlg::~HYDROGUI_MeasurementToolDlg()
+{
+}
+
+void HYDROGUI_MeasurementToolDlg::setTotalDst(QString strVal)
+{
+ myTotalDst->setText(strVal);
+}
+
+bool HYDROGUI_MeasurementToolDlg::IsLDChecked() const
+{
+ return mySwitcherLD->isChecked();
+}
+
+void HYDROGUI_MeasurementToolDlg::setPolylineNames(QStringList thePolyNames)
+{
+ myPolylinesCBox->clear();
+ foreach (QString aName, thePolyNames)
+ myPolylinesCBox->addItem(aName);
+}
+
+int HYDROGUI_MeasurementToolDlg::currentSelectedPolyline() const
+{
+ return myPolylinesCBox->currentIndex();
+}
+
+bool HYDROGUI_MeasurementToolDlg::GetExitFlag() const
+{
+ return myExit;
+}
+
+void HYDROGUI_MeasurementToolDlg::onExit()
+{
+ myExit = true;
+ emit doExit();
+}
+
+void HYDROGUI_MeasurementToolDlg::onClear()
+{
+ emit clearLine();
+}
+
+void HYDROGUI_MeasurementToolDlg::onSetMode(bool mode)
+{
+ emit onClear();
+ if (mode)
+ myPolylinesCBox->setDisabled(true);
+ else
+ myPolylinesCBox->setDisabled(false);
+}
+
+
+
--- /dev/null
+// Copyright (C) 2014-2015 EDF-R&D
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "HYDROGUI_MeasurementToolOp.h"
+
+#include "HYDROGUI_DataModel.h"
+#include "HYDROGUI_Module.h"
+
+#include <HYDROData_Object.h>
+#include <HYDROData_IPolyline.h>
+
+#include <LightApp_Application.h>
+
+#include <SUIT_Desktop.h>
+#include <HYDROGUI_Tool2.h>
+#include <HYDROGUI_MeasurementToolDlg.h>
+#include <OCCViewer_ViewModel.h>
+#include <OCCViewer_ViewManager.h>
+#include <OCCViewer_ViewPort3d.h>
+#include <OCCViewer_ViewWindow.h>
+#include <BRep_Builder.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Compound.hxx>
+#include <AIS_Shape.hxx>
+#include <CurveCreator_Utils.hxx>
+#include <QMouseEvent>
+#include <TopExp.hxx>
+#include <HYDROData_Iterator.h>
+#include <HYDROData_PolylineXY.h>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <TopoDS.hxx>
+#include <vector>
+#include <utility>
+#include <Prs3d_Drawer.hxx>
+#include <BRepAlgo.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <BRepLib_MakePolygon.hxx>
+
+
+HYDROGUI_MeasurementToolOp::HYDROGUI_MeasurementToolOp( HYDROGUI_Module* theModule )
+ : HYDROGUI_Operation( theModule ),
+ myMeasDlg(0),
+ myLineMaker(NULL),
+ myAISLineM(NULL),
+ myDist(0),
+ // myFAd(NULL),
+ myFu(0)
+{
+ setName( tr( "MEASUREMENT_TOOL" ) );
+}
+
+HYDROGUI_MeasurementToolOp::~HYDROGUI_MeasurementToolOp()
+{
+ if (myLineMaker)
+ delete myLineMaker;
+}
+
+void HYDROGUI_MeasurementToolOp::startOperation()
+{
+ HYDROGUI_Operation::startOperation();
+
+ myMeasDlg = new HYDROGUI_MeasurementToolDlg( module()->getApp()->desktop() );
+ myMeasDlg->setModal( false );
+ myMeasDlg->setWindowTitle(getName());
+ myMeasDlg->show();
+
+ //Tool: draw a distance line
+ LightApp_Application* anApp = module()->getApp();
+ OCCViewer_ViewManager* aViewManager =
+ dynamic_cast<OCCViewer_ViewManager*>( anApp->getViewManager( OCCViewer_Viewer::Type(), true ) );
+
+ setPreviewManager( aViewManager );
+
+ connect( myMeasDlg, SIGNAL( clearLine() ), this, SLOT( onClearLine() ) );
+
+ connect( myMeasDlg, SIGNAL( doExit() ), this, SLOT( onExit() ) );
+
+ OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
+
+ disconnect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
+ aViewer, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
+ connect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
+ this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
+
+ //polyline names
+ HYDROData_Iterator anIter( doc(), KIND_POLYLINEXY );
+ QStringList aPolylineNames;
+ myPolyObjs.clear();
+ for ( ; anIter.More(); anIter.Next() )
+ {
+ Handle(HYDROData_PolylineXY) aPolylineObj = Handle(HYDROData_PolylineXY)::DownCast( anIter.Current() );
+ myPolyObjs.push_back(aPolylineObj);
+ aPolylineNames << aPolylineObj->GetName();
+ }
+ myMeasDlg->setPolylineNames(aPolylineNames);
+}
+
+void HYDROGUI_MeasurementToolOp::onClearLine()
+{
+ eraseLine();
+ myDist = 0;
+ //myPolyObjs.clear();
+ myMeasDlg->setTotalDst(0);
+ delete myLineMaker;
+ myLineMaker = NULL;
+ myFW = TopoDS_Wire();
+}
+
+void HYDROGUI_MeasurementToolOp::onMousePress(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
+{
+ OCCViewer_ViewManager* aViewManager = getPreviewManager();
+ if ( !aViewManager )
+ return;
+
+ OCCViewer_ViewWindow* aViewWindow = (OCCViewer_ViewWindow*)aViewManager->getActiveView();
+ if ( !aViewWindow )
+ return;
+
+ OCCViewer_ViewPort3d* aViewPort = aViewWindow->getViewPort();
+ if ( !aViewPort )
+ return;
+
+ Handle(V3d_View) aView = aViewPort->getView();
+ if ( aView.IsNull() )
+ return;
+
+ OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
+ if ( !aViewer )
+ return;
+
+ Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
+ if ( aCtx.IsNull() )
+ return;
+
+ gp_Pnt aPnt = CurveCreator_Utils::ConvertClickToPoint( theEvent->x(), theEvent->y(), aView );
+
+ TopoDS_Shape aRes;
+
+ if (myMeasDlg->IsLDChecked())
+ {
+ if (!myLineMaker)
+ {
+ myLineMaker = new BRepLib_MakePolygon();
+ myLineMaker->Add(aPnt);
+ aRes = myLineMaker->FirstVertex();
+ }
+ else
+ {
+ myLineMaker->Add(aPnt);
+ aRes = myLineMaker->Shape();
+ const TopoDS_Edge& aLE = myLineMaker->Edge();
+ TopoDS_Vertex aFV = TopExp::FirstVertex(aLE, true);
+ TopoDS_Vertex aLV = TopExp::LastVertex(aLE, true);
+ double aNDist = BRep_Tool::Pnt(aFV).Distance(BRep_Tool::Pnt(aLV));
+ myDist += aNDist;
+ myMeasDlg->setTotalDst(QString::number(myDist));
+ }
+
+ if ( !myAISLineM.IsNull() )
+ {
+ if ( aCtx->HasOpenedContext() )
+ aCtx->CloseLocalContext();
+ aCtx->Erase( myAISLineM, Standard_False );
+ }
+ }
+ else
+ {
+ double prec = 70; //minimum precision
+ int selectInd = myMeasDlg->currentSelectedPolyline();
+ if (selectInd == -1)
+ return;
+ Handle(HYDROData_PolylineXY) aPolylineObj = myPolyObjs[selectInd];
+ TopoDS_Shape aShape = aPolylineObj->GetShape();
+ TopExp_Explorer exp(aShape, TopAbs_WIRE);
+ double fdist_min = RealLast();
+ TopoDS_Wire minWire;
+ BRepAdaptor_Curve minC;
+ double minU;
+ for (;exp.More(); exp.Next())
+ {
+ TopoDS_Wire W = TopoDS::Wire(exp.Current());
+ if (W.IsNull())
+ continue;
+ TopExp_Explorer expW(W, TopAbs_EDGE);
+ if (!expW.More())
+ continue;
+ TopoDS_Edge E = TopoDS::Edge(expW.Current());
+ expW.Next();
+ if (expW.More())
+ E = BRepAlgo::ConcatenateWireC0(W);
+ BRepAdaptor_Curve Ad(E);
+ Handle(Geom_BSplineCurve) aBsp = Ad.Curve().BSpline();
+ std::vector<double> params;
+ double Fp = Ad.FirstParameter();
+ double Lp = Ad.LastParameter();
+ params.push_back(Fp);
+ params.push_back(Lp);
+ if (!aBsp.IsNull())
+ {
+ TColStd_Array1OfReal aKnots = aBsp->Knots();
+ for (int i = 1; i <= aKnots.Size(); i++)
+ {
+ if (aKnots(i) > Fp && aKnots(i) < Lp)
+ params.push_back(aKnots(i));
+ }
+ }
+ //in some cases, extrema gives inaccurate result ->
+ //split bspline by knot params and try to find minimum distance
+ //on each interval
+ std::sort(params.begin(), params.end());
+ for (int i = 0; i < params.size() - 1; i++ )
+ {
+ //Extrema_ExtPC extrema(aPnt, Ad, params[i], params[i+1]);
+ GeomAPI_ProjectPointOnCurve aProj; //extrema wrapper
+ aProj.Init (aPnt, Ad.Curve().Curve(), params[i], params[i+1]);
+ if (aProj.NbPoints() > 0)
+ {
+ double fdist = aProj.LowerDistance();
+ gp_Pnt aFP = aProj.NearestPoint();
+ int x1=-1, y1=-1, x2=-1, y2=-1;
+ CurveCreator_Utils::ConvertPointToClick(aPnt, aView, x1, y1);
+ CurveCreator_Utils::ConvertPointToClick(aFP, aView, x2, y2);
+ gp_Pnt2d pp1((double)x1, (double)y1);
+ gp_Pnt2d pp2((double)x2, (double)y2);
+ int aWinSX, aWinSY;
+ aView->Window()->Size(aWinSX, aWinSY);
+ double pd = pp1.Distance(pp2);
+ double WinDiagDist = sqrt ((double)aWinSX*(double)aWinSX + (double)aWinSY*(double)aWinSY);
+ if (fdist <= prec || pd / WinDiagDist < 0.08)
+ {
+ if (fdist < fdist_min)
+ {
+ fdist_min = fdist;
+ minWire = W;
+ minU = aProj.LowerDistanceParameter();
+ minC.Initialize(E);
+ }
+ }
+ }
+ }
+ }
+ //
+ if (!minWire.IsNull())
+ {
+ if (myFW.IsNull())
+ {
+ myFu = minU;
+ myFW = minWire;
+ aRes = BRepLib_MakeVertex(aPnt);
+ }
+ else
+ {
+ if (myFW.IsSame(minWire))
+ {
+ //calc distance on current curve
+ double LenAlongCurv = GCPnts_AbscissaPoint::Length(minC, myFu, minU);
+ myFW = TopoDS_Wire();
+ if (!BRep_Tool::IsClosed(minWire))
+ {
+ aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
+ myMeasDlg->setTotalDst(QString::number(LenAlongCurv));
+ }
+ else
+ {
+ double Len2 = GCPnts_AbscissaPoint::Length(minC) - LenAlongCurv;
+ if (LenAlongCurv < Len2)
+ aRes = BRepLib_MakeEdge(minC.Curve().Curve(), Min(myFu, minU), Max (myFu, minU));
+ else
+ {
+ TopoDS_Compound aCmpEd;
+ BRep_Builder aB;
+ aB.MakeCompound(aCmpEd);
+ aB.Add(aCmpEd, BRepLib_MakeEdge(minC.Curve().Curve(), minC.FirstParameter(), Min(myFu, minU)));
+ aB.Add(aCmpEd, BRepLib_MakeEdge(minC.Curve().Curve(), Max(myFu, minU), minC.LastParameter()));
+ aRes = aCmpEd;
+ }
+ myMeasDlg->setTotalDst(QString::number(LenAlongCurv) + ", " + QString::number(Len2));
+ }
+ }
+ }
+ }
+ }
+
+ if (aRes.IsNull())
+ return;
+
+ aCtx->Erase( myAISLineM, Standard_False );
+
+ myAISLineM = new AIS_Shape( aRes );
+
+ myAISLineM->SetColor( Quantity_NOC_ORANGE );
+ //Handle(Prs3d_Drawer) aHA = myAISLineM->HilightAttributes();
+
+ myAISLineM->SetWidth( 3 );
+ //Handle(Prs3d_PointAspect) anAspect = mySplitPointPreview->Attributes()->PointAspect();
+ //anAspect->SetScale(2.0);
+ //anAspect->SetTypeOfMarker(Aspect_TOM_RING1);
+ //anAspect->SetColor(Quantity_NOC_BLACK);
+ //mySplitPointPreview->Attributes()->SetPointAspect( anAspect );
+
+ aCtx->SetZLayer(myAISLineM, Graphic3d_ZLayerId_Topmost);
+
+ if ( aCtx->HasOpenedContext() )
+ aCtx->CloseLocalContext();
+ aCtx->Display( myAISLineM, Standard_False );
+ aCtx->UpdateCurrentViewer();
+}
+
+void HYDROGUI_MeasurementToolOp::eraseLine()
+{
+ OCCViewer_ViewManager* aViewManager = getPreviewManager();
+ if ( aViewManager )
+ {
+ if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() )
+ {
+ if ( !myAISLineM.IsNull() )
+ {
+ Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
+ if ( !aCtx.IsNull() )
+ {
+ if ( aCtx->HasOpenedContext() )
+ aCtx->CloseLocalContext();
+ aCtx->Erase( myAISLineM, Standard_False );
+ }
+ myAISLineM.Nullify();
+ aCtx->UpdateCurrentViewer();
+ }
+ }
+ }
+}
+
+void HYDROGUI_MeasurementToolOp::abortOperation()
+{
+ if (!myMeasDlg->GetExitFlag())
+ myMeasDlg->done(0);
+}
+
+void HYDROGUI_MeasurementToolOp::onExit()
+{
+ onClearLine();
+ OCCViewer_ViewManager* aViewManager = getPreviewManager();
+ OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer();
+
+ if (aViewManager && aViewer)
+ {
+ disconnect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
+ this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
+
+ connect(aViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
+ aViewManager->getOCCViewer(), SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
+ }
+
+ if (myLineMaker)
+ delete myLineMaker;
+
+ this->blockSignals(true);
+ HYDROGUI_Operation::abort();
+ this->blockSignals(false);
+}
+
+
+
+
+