From 2b4e07192365d3cf91c61f432351f762385bc3d8 Mon Sep 17 00:00:00 2001 From: skv Date: Tue, 7 Oct 2014 17:37:18 +0400 Subject: [PATCH] Implementation of Polyline dialog --- src/CurveCreator/CurveCreator_Utils.cxx | 457 +++++++++++++++++++++++ src/CurveCreator/CurveCreator_Utils.hxx | 74 +++- src/CurveCreator/CurveCreator_Widget.cxx | 20 +- src/CurveCreator/CurveCreator_Widget.h | 4 + src/EntityGUI/EntityGUI_PolylineDlg.cxx | 370 ++++++++++++++++-- src/EntityGUI/EntityGUI_PolylineDlg.h | 55 ++- src/GEOMGUI/GEOM_msg_en.ts | 4 + 7 files changed, 933 insertions(+), 51 deletions(-) diff --git a/src/CurveCreator/CurveCreator_Utils.cxx b/src/CurveCreator/CurveCreator_Utils.cxx index ea8da226f..146676c95 100644 --- a/src/CurveCreator/CurveCreator_Utils.cxx +++ b/src/CurveCreator/CurveCreator_Utils.cxx @@ -19,6 +19,7 @@ #include "CurveCreator_Utils.hxx" #include "CurveCreator.hxx" +#include "CurveCreator_Curve.hxx" #include "CurveCreator_UtilsICurve.hxx" #include @@ -41,9 +42,12 @@ #include #include #include +#include +#include #include #include +#include #include #include #include @@ -54,9 +58,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -71,6 +77,48 @@ const double LOCAL_SELECTION_TOLERANCE = 0.0001; const int SCENE_PIXEL_PROJECTION_TOLERANCE = 10; const int SCENE_PIXEL_POINT_TOLERANCE = 5; +#define PLN_FREE 0 +#define PLN_ORIGIN 1 +#define PLN_OX 2 +#define PLN_FIXED 3 + +/** + * This static function returns the curve of original type from the edge. + * + * \param theEdge the edge + * \return the curve of original type. Can be null handle. + */ +static Handle(Geom_Curve) GetCurve(const TopoDS_Edge &theEdge) +{ + Handle(Geom_Curve) aResult; + + if (theEdge.IsNull()) { + return aResult; + } + + Standard_Real aF; + Standard_Real aL; + + aResult = BRep_Tool::Curve(theEdge, aF, aL); + + if (aResult.IsNull()) { + return aResult; + } + + // Get the curve of original type + Handle(Standard_Type) aType = aResult->DynamicType(); + + while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) { + Handle(Geom_TrimmedCurve) aTrCurve = + Handle(Geom_TrimmedCurve)::DownCast(aResult); + + aResult = aTrCurve->BasisCurve(); + aType = aResult->DynamicType(); + } + + return aResult; +} + //======================================================================= // function : ConvertClickToPoint() // purpose : Returns the point clicked in 3D view @@ -245,6 +293,200 @@ void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve, theShape = aComp; } +/** + * This is an intermediate structure for curve construction. + */ +struct Section3D +{ + Section3D() : myIsClosed(false), myIsBSpline(false) + { } + + bool myIsClosed; + bool myIsBSpline; + Handle(TColgp_HArray1OfPnt) myPoints; +}; + +//======================================================================= +// function : constructCurve +// purpose : +//======================================================================= +bool CurveCreator_Utils::constructCurve + (const TopoDS_Shape theShape, + CurveCreator_Curve *theCurve, + gp_Ax3 &theLocalCS) +{ + if (theShape.IsNull()) { + return false; + } + + // Collect wires or vertices from shape. + TopTools_ListOfShape aWOrV; + TopAbs_ShapeEnum aType = theShape.ShapeType(); + + if (aType == TopAbs_WIRE || aType == TopAbs_VERTEX) { + aWOrV.Append(theShape); + } else if (aType == TopAbs_COMPOUND) { + TopoDS_Iterator aShIter(theShape); + + for (; aShIter.More(); aShIter.Next()) { + const TopoDS_Shape &aSubShape = aShIter.Value(); + + aType = aSubShape.ShapeType(); + + if (aType == TopAbs_WIRE || aType == TopAbs_VERTEX) { + aWOrV.Append(aSubShape); + } else { + // Only subshapes of types wire or vertex are supported. + return false; + } + } + } else { + // Only wire (vertex) or compound of wires (vertices) are supported. + return false; + } + + // Treat each wire or vertex. Get points, compute the working plane. + gp_Pln aPlane; + Standard_Integer aPlaneStatus = PLN_FREE; + TopTools_ListIteratorOfListOfShape anIter(aWOrV); + std::list aListSec; + + for (; anIter.More(); anIter.Next()) { + Section3D aSec3D; + + aSec3D.myPoints = CurveCreator_Utils::getPoints + (anIter.Value(), aSec3D.myIsClosed, aSec3D.myIsBSpline); + + if (aSec3D.myPoints.IsNull()) { + return false; + } + + aListSec.push_back(aSec3D); + + if (aPlaneStatus != PLN_FIXED) { + // Compute plane + CurveCreator_Utils::FindPlane(aSec3D.myPoints, aPlane, aPlaneStatus); + } + } + + // Check if it is possible to change a computed coordinate system by + // XOY, XOZ or YOZ or parallel to them. + gp_Pnt aO(0., 0., 0.); + gp_Dir aNDir(0., 0., 1.); + gp_Dir aXDir(1., 0., 0.); + gp_Ax3 anAxis; + Standard_Real aTolAng = Precision::Confusion(); // Angular() is too small. + + switch (aPlaneStatus) { + case PLN_ORIGIN: + { + // Change the location. + aO.SetZ(aPlane.Location().Z()); + anAxis.SetLocation(aO); + aPlane.SetPosition(anAxis); + } + break; + case PLN_OX: + { + // Fixed origin + OX axis + const gp_Dir &aPlnX = aPlane.Position().XDirection(); + + if (Abs(aPlnX.Z()) <= aTolAng) { + // Make a coordinate system parallel to XOY. + aO.SetZ(aPlane.Location().Z()); + anAxis.SetLocation(aO); + aPlane.SetPosition(anAxis); + } else if (Abs(aPlnX.Y()) <= aTolAng) { + // Make a coordinate system parallel to XOZ. + aO.SetY(aPlane.Location().Y()); + aNDir.SetCoord(0., 1., 0.); + aXDir.SetCoord(0., 0., 1.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } else if (Abs(aPlnX.X()) <= aTolAng) { + // Make a coordinate system parallel to YOZ. + aO.SetX(aPlane.Location().X()); + aNDir.SetCoord(1., 0., 0.); + aXDir.SetCoord(0., 1., 0.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } + } + break; + case PLN_FIXED: + { + const gp_Dir &aPlnN = aPlane.Position().Direction(); + gp_Dir aYDir(0., 1., 0.); + + if (aPlnN.IsParallel(aNDir, aTolAng)) { + // Make a coordinate system parallel to XOY. + aO.SetZ(aPlane.Location().Z()); + anAxis.SetLocation(aO); + aPlane.SetPosition(anAxis); + } else if (aPlnN.IsParallel(aYDir, aTolAng)) { + // Make a coordinate system parallel to XOZ. + aO.SetY(aPlane.Location().Y()); + aNDir.SetCoord(0., 1., 0.); + aXDir.SetCoord(0., 0., 1.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } else if (aPlnN.IsParallel(aXDir, aTolAng)) { + // Make a coordinate system parallel to YOZ. + aO.SetX(aPlane.Location().X()); + aNDir.SetCoord(1., 0., 0.); + aXDir.SetCoord(0., 1., 0.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } + } + break; + case PLN_FREE: + default: + // Use XOY plane. + aPlane.SetPosition(anAxis); + break; + } + + // Compute 2d points. + std::list::const_iterator aSecIt = aListSec.begin(); + Standard_Real aTolConf2 = + Precision::Confusion()*Precision::Confusion(); + Standard_Real aX; + Standard_Real aY; + + for (; aSecIt != aListSec.end(); ++aSecIt) { + Standard_Integer i; + CurveCreator::Coordinates aCoords; + + for (i = aSecIt->myPoints->Lower(); i <= aSecIt->myPoints->Upper(); ++i) { + const gp_Pnt &aPnt = aSecIt->myPoints->Value(i); + + if (aPlane.SquareDistance(aPnt) > aTolConf2) { + // The point doesn't lie on the plane. + return false; + } + + ElSLib::Parameters(aPlane, aPnt, aX, aY); + aCoords.push_back(aX); + aCoords.push_back(aY); + } + + // Add a new section to the curve. + const std::string aSecName = + CurveCreator_UtilsICurve::getUniqSectionName(theCurve); + const CurveCreator::SectionType aSecType = aSecIt->myIsBSpline ? + CurveCreator::Spline : CurveCreator::Polyline; + + theCurve->addSectionInternal(aSecName, aSecType, + aSecIt->myIsClosed, aCoords); + } + + // Set the local coordinate system. + theLocalCS = aPlane.Position(); + + return true; +} + class CompareSectionToPoint { public: @@ -535,3 +777,218 @@ bool CurveCreator_Utils::isEqualPoints( const gp_Pnt& thePoint, const gp_Pnt& th { return theOtherPoint.IsEqual( thePoint, LOCAL_SELECTION_TOLERANCE ); } + +//======================================================================= +// function : getPoints +// purpose : +//======================================================================= +Handle(TColgp_HArray1OfPnt) CurveCreator_Utils::getPoints + (const TopoDS_Shape &theShape, + bool &IsClosed, + bool &IsBSpline) +{ + Handle(TColgp_HArray1OfPnt) aResult; + + IsClosed = false; + IsBSpline = false; + + if (theShape.IsNull()) { + return aResult; + } + + const TopAbs_ShapeEnum aShType = theShape.ShapeType(); + + if (aShType == TopAbs_VERTEX) { + // There is a single point. + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape)); + + aResult = new TColgp_HArray1OfPnt(1, 1, aPnt); + + return aResult; + } else if (aShType != TopAbs_WIRE) { + // The shape is neither a vertex nor a wire. + return aResult; + } + + // Treat wire. + BRepTools_WireExplorer anExp(TopoDS::Wire(theShape)); + + if (!anExp.More()) { + // Empty wires are not allowed. + return aResult; + } + + // Treat the first edge. + TopoDS_Edge anEdge = anExp.Current(); + Handle(Geom_Curve) aCurve = GetCurve(anEdge); + + if (aCurve.IsNull()) { + return aResult; + } + + // Check the curve type. + Handle(Standard_Type) aType = aCurve->DynamicType(); + + if (aType == STANDARD_TYPE(Geom_BSplineCurve)) { + IsBSpline = true; + } else if (aType != STANDARD_TYPE(Geom_Line)) { + // The curve is neither a line or a BSpline. It is not valid. + return aResult; + } + + // Go to the next edge. + TopoDS_Vertex aFirstVtx = anExp.CurrentVertex(); + + anExp.Next(); + + if (IsBSpline) { + // There should be a single BSpline curve in the wire. + if (anExp.More()) { + return aResult; + } + + // Construct a section from poles of BSpline. + Handle(Geom_BSplineCurve) aBSplCurve = + Handle(Geom_BSplineCurve)::DownCast(aCurve); + + // Check if the edge is valid. It should not be based on trimmed curve. + gp_Pnt aCP[2] = { aBSplCurve->StartPoint(), aBSplCurve->EndPoint() }; + TopoDS_Vertex aV[2]; + Standard_Integer i; + + TopExp::Vertices(anEdge, aV[0], aV[1]); + + for (i = 0; i < 2; i++) { + gp_Pnt aPnt = BRep_Tool::Pnt(aV[i]); + Standard_Real aTol = BRep_Tool::Tolerance(aV[i]); + + if (!aPnt.IsEqual(aCP[i], aTol)) { + return aResult; + } + } + + IsClosed = aV[0].IsSame(aV[1]) ? true : false; + + const Standard_Integer aNbPoints = aBSplCurve->NbKnots(); + TColStd_Array1OfReal aKnots(1, aNbPoints); + + aBSplCurve->Knots(aKnots); + aResult = new TColgp_HArray1OfPnt(1, aBSplCurve->NbKnots()); + + for (i = aKnots.Lower(); i <= aKnots.Upper(); ++i) { + aResult->SetValue(i, aBSplCurve->Value(aKnots.Value(i))); + } + } else { + // This is a polyline. + TopTools_ListOfShape aVertices; + Standard_Integer aNbVtx = 1; + + + aVertices.Append(aFirstVtx); + + for (; anExp.More(); anExp.Next(), ++aNbVtx) { + anEdge = anExp.Current(); + aCurve = GetCurve(anEdge); + + if (aCurve.IsNull()) { + return aResult; + } + + aType = aCurve->DynamicType(); + + if (aType != STANDARD_TYPE(Geom_Line)) { + // The curve is not a line. It is not valid. + return aResult; + } + + // Add the current vertex to the list. + aVertices.Append(anExp.CurrentVertex()); + } + + // Check if the section is closed. + TopoDS_Vertex aLastVtx = TopExp::LastVertex(anEdge, Standard_True); + + IsClosed = aFirstVtx.IsSame(aLastVtx) ? true : false; + + // Fill the array of points. + aResult = new TColgp_HArray1OfPnt(1, aNbVtx); + + Standard_Integer i; + TopTools_ListIteratorOfListOfShape aVtxIter(aVertices); + + for (i = 1; aVtxIter.More(); aVtxIter.Next(), ++i) { + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVtxIter.Value())); + + aResult->SetValue(i, aPnt); + } + } + + return aResult; +} +//======================================================================= +// function : FindPlane +// purpose : +//======================================================================= +void CurveCreator_Utils::FindPlane + (const Handle_TColgp_HArray1OfPnt &thePoints, + gp_Pln &thePlane, + Standard_Integer &thePlnStatus) +{ + if (thePoints.IsNull() || thePlnStatus == PLN_FIXED) { + // The plane can't be defined or is fixed. Nothing to change. + return; + } + + Standard_Integer i; + const Standard_Real aTolConf = Precision::Confusion(); + + for (i = thePoints->Lower(); i <= thePoints->Upper(); ++i) { + const gp_Pnt &aPnt = thePoints->Value(i); + + switch (thePlnStatus) { + case PLN_FREE: + // Fix the origin. + thePlane.SetLocation(aPnt); + thePlnStatus = PLN_ORIGIN; + break; + case PLN_ORIGIN: + { + // Fix origin + OX axis + const gp_Pnt &aPlnLoc = thePlane.Location(); + + if (!aPnt.IsEqual(aPlnLoc, aTolConf)) { + // Set the X axis. + gp_Dir aXDir(aPnt.XYZ().Subtracted(aPlnLoc.XYZ())); + gp_Ax3 aXNorm(aPlnLoc, aXDir); + gp_Ax3 aNewPlnPos(aPlnLoc, aXNorm.XDirection(), aXNorm.Direction()); + + thePlane.SetPosition(aNewPlnPos); + thePlnStatus = PLN_OX; + } + } + break; + case PLN_OX: + { + // Fix OY axis + gp_Lin aXLin(thePlane.XAxis()); + Standard_Real aSqrDist = aXLin.SquareDistance(aPnt); + + if (aSqrDist > aTolConf*aTolConf) { + // Compute main axis. + const gp_Pnt &aPlnLoc = thePlane.Location(); + gp_Dir aDir(aPnt.XYZ().Subtracted(aPlnLoc.XYZ())); + gp_Ax3 aXNorm(aPlnLoc, aXLin.Direction(), aDir); + gp_Ax3 aNewPlnPos(aPlnLoc, aXNorm.YDirection(), + aXNorm.Direction()); + + thePlane.SetPosition(aNewPlnPos); + thePlnStatus = PLN_FIXED; + return; + } + } + break; + default: + return; + } + } +} diff --git a/src/CurveCreator/CurveCreator_Utils.hxx b/src/CurveCreator/CurveCreator_Utils.hxx index 0cf2364da..8dddaf2ff 100644 --- a/src/CurveCreator/CurveCreator_Utils.hxx +++ b/src/CurveCreator/CurveCreator_Utils.hxx @@ -29,10 +29,13 @@ #include #include #include +#include #include #include // TODO: remove +class CurveCreator_Curve; + class CurveCreator_Utils { @@ -69,6 +72,19 @@ public: CURVECREATOR_EXPORT static void constructShape( const CurveCreator_ICurve* theCurve, TopoDS_Shape& theShape ); + /** + * Generates a curve from a shape. + * \param theShape a shape to be converted to curve. + * \param theCurve a curve object to be initialized. + * \param theLocalCS the local coordinate system of the curve. + * \return true in case of success; false otherwise. Warning: the curve can + * be modified even if the shape is not valid for curve construction. + */ + CURVECREATOR_EXPORT static bool constructCurve + (const TopoDS_Shape theShape, + CurveCreator_Curve *theCurve, + gp_Ax3 &theLocalCS); + /** * Find selected points in the context * \param theContext the viewer context @@ -124,12 +140,12 @@ protected: * \param theCurve a geometry curve * \param theOutPoint a found projected point on the curve */ - CURVECREATOR_EXPORT static bool hasProjectPointOnCurve( - Handle(V3d_View) theView, - const int theX, const int theY, - const Handle(Geom_Curve)& theCurve, - Standard_Real& theParameter, - int& theDelta ); + static bool hasProjectPointOnCurve( + Handle(V3d_View) theView, + const int theX, const int theY, + const Handle(Geom_Curve)& theCurve, + Standard_Real& theParameter, + int& theDelta ); /* * Returns whether the X and Y coordinates is in the pixel tolerance @@ -141,9 +157,9 @@ protected: * \param theDelta the sum of the a square of X and a square of Y * \returns whether the points are provide to the pixel tolerance */ - CURVECREATOR_EXPORT static bool isEqualPixels( const int theX, const int theY, - const int theOtherX, const int theOtherY, - const double theTolerance, int& theDelta ); + static bool isEqualPixels( const int theX, const int theY, + const int theOtherX, const int theOtherY, + const double theTolerance, int& theDelta ); /* @@ -152,8 +168,44 @@ protected: * \param theOtherPoint the second point * \returns whether the points are provide to the pixel tolerance */ - CURVECREATOR_EXPORT static bool isEqualPoints( const gp_Pnt& thePoint, - const gp_Pnt& theOtherPoint ); + static bool isEqualPoints( const gp_Pnt& thePoint, + const gp_Pnt& theOtherPoint ); + + /** + * Returns the array of points of a shape to construct a curve section. The + * shape can be either a wire or a vertex. For vertex a single point in the + * array is returned. + * + * \param theShape the shape. Can be either a wire or a vertex. + * \param IsClosed closed flag. Output parameter. + * \param IsBSpline BSpline flag. Output parameter. + * \return the array of points. Null handle in case of failure. + */ + static Handle_TColgp_HArray1OfPnt getPoints + (const TopoDS_Shape &theShape, + bool &IsClosed, + bool &IsBSpline); + + /** + * This method computes a plane using the input points. The plane is defined + * by gp_Pln object and the status. The status can have one of the following + * values: + * - 0 plane is not set.
+ * - 1 origin of the plane is fixed. The plane is defined by 1 or several + * coincident points.
+ * - 2 origin + OX axis of the plane is fixed. The plane is defined by 2 + * or more points that lie on a particular line.
+ * - 3 plane is fixed. Plane is defined by 3 not coincident points.
+ * + * \param thePoints the points. + * \param thePlane the current plane on input. It can be modified on output. + * \param thePlnStatus the current status on input. It can be modified on + * output. + */ + static void FindPlane(const Handle_TColgp_HArray1OfPnt &thePoints, + gp_Pln &thePlane, + Standard_Integer &thePlnStatus); + }; #endif // CURVECREATOR_UTILS_H diff --git a/src/CurveCreator/CurveCreator_Widget.cxx b/src/CurveCreator/CurveCreator_Widget.cxx index b90e1fe19..f22d8f67d 100644 --- a/src/CurveCreator/CurveCreator_Widget.cxx +++ b/src/CurveCreator/CurveCreator_Widget.cxx @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -84,7 +83,8 @@ CurveCreator_Widget::CurveCreator_Widget(QWidget* parent, int theLocalPointRowLimit ) : QWidget(parent), myNewSectionEditor(NULL), myCurve(theCurve), mySection(0), myDragStarted( false ), myDragInteractionStyle( SUIT_ViewModel::STANDARD ), - myOCCViewer( 0 ), myLocalPointRowLimit( theLocalPointRowLimit ) + myOCCViewer( 0 ), myLocalPointRowLimit( theLocalPointRowLimit ), + myOld2DMode(OCCViewer_ViewWindow::No2dMode) { bool isToEnableClosed = !( theActionFlags & DisableClosedSection ); myNewSectionEditor = new CurveCreator_NewSectionDlg( this, isToEnableClosed ); @@ -240,7 +240,7 @@ void CurveCreator_Widget::setOCCViewer( OCCViewer_Viewer* theViewer ) disconnect( aViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ), this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) ); // restore normal mode in the viewer - OCCViewer_Utilities::setViewer2DMode( myOCCViewer, OCCViewer_ViewWindow::No2dMode ); + SetViewer2DMode(false); // all local contexts should be closed if the viewer is not more used setLocalPointContext( false, true ); } @@ -257,7 +257,7 @@ void CurveCreator_Widget::setOCCViewer( OCCViewer_Viewer* theViewer ) this, SLOT( onMouseMove( SUIT_ViewWindow*, QMouseEvent* ) ) ); connect( aViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ), this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) ); - OCCViewer_Utilities::setViewer2DMode( myOCCViewer, OCCViewer_ViewWindow::XYPlane ); + SetViewer2DMode(true); } } @@ -946,6 +946,18 @@ CurveCreator_Widget::ActionMode CurveCreator_Widget::getActionMode() const return aMode; } +void CurveCreator_Widget::SetViewer2DMode(const bool To2D) +{ + if (myOCCViewer) { + if (To2D) { + myOld2DMode = OCCViewer_Utilities::setViewer2DMode + (myOCCViewer, OCCViewer_ViewWindow::XYPlane); + } else { + OCCViewer_Utilities::setViewer2DMode(myOCCViewer, myOld2DMode); + } + } +} + //================================================================================= // function : GeometryGUI::addCoordsByClick() // purpose : Manage mouse press events in Additon mode diff --git a/src/CurveCreator/CurveCreator_Widget.h b/src/CurveCreator/CurveCreator_Widget.h index 2baf2f590..e15e92309 100644 --- a/src/CurveCreator/CurveCreator_Widget.h +++ b/src/CurveCreator/CurveCreator_Widget.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -93,6 +94,8 @@ public: void setActionMode( const ActionMode& theMode ); ActionMode getActionMode() const; + void SetViewer2DMode(const bool To2D); + signals: void selectionChanged(); void subOperationStarted( QWidget*, bool ); @@ -222,6 +225,7 @@ private: QByteArray myGuiState; int myPressedX; int myPressedY; + OCCViewer_ViewWindow::Mode2dType myOld2DMode; }; #endif // CURVECREATOR_WIDGET_H diff --git a/src/EntityGUI/EntityGUI_PolylineDlg.cxx b/src/EntityGUI/EntityGUI_PolylineDlg.cxx index ed748631d..50c12462a 100644 --- a/src/EntityGUI/EntityGUI_PolylineDlg.cxx +++ b/src/EntityGUI/EntityGUI_PolylineDlg.cxx @@ -22,18 +22,27 @@ #include "EntityGUI_PolylineDlg.h" #include +#include #include #include #include +#include #include +#include #include #include #include +#include +#include +#include +#include + #include #include +//#define SET_PLANE //================================================================================= // function : Constructor @@ -41,9 +50,20 @@ //================================================================================= EntityGUI_PolylineDlg::EntityGUI_PolylineDlg (GeometryGUI* theGeometryGUI, QWidget* parent, bool modal, Qt::WindowFlags fl) - : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ) + : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ), + myCurve (0), + myEditorWidget (0), + myAddElementBox (0), + myPlnComboBox (0), + myPlnButton (0), + myPlnSelButton (0), + myWPlaneLineEdit (0), + myPolylineSelButton (0), + myPolylineEdit (0), + myEditCurrentArgument (0) { - QPixmap image0( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_CC_POLYLINE" ) ) ); + QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_CC_POLYLINE"))); + QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT"))); setWindowTitle(tr("POLYLINE_DLG_TITLE")); @@ -55,6 +75,46 @@ EntityGUI_PolylineDlg::EntityGUI_PolylineDlg mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose ); mainFrame()->RadioButton3->close(); + QGroupBox *aGroupBox1 = new QGroupBox(tr("GEOM_CS"), this); + QGridLayout *aPlaneLayout = new QGridLayout(aGroupBox1); + + aPlaneLayout->setSpacing(6); + aPlaneLayout->setMargin(11); + + myPlnComboBox = new QComboBox(aGroupBox1); + aPlaneLayout->addWidget(myPlnComboBox, 0, 0, 1, 3); + + myPlnButton = new QPushButton (aGroupBox1); + myPlnButton->setText( tr( "GEOM_SKETCHER_RESTORE" ) ); + aPlaneLayout->addWidget(myPlnButton, 0, 3); + +#ifdef SET_PLANE + QLabel *aPlaneLbl = new QLabel(tr("GEOM_PLANE"), aGroupBox1); + + myPlnSelButton = new QPushButton (aGroupBox1); + myPlnSelButton->setIcon(image1); + myWPlaneLineEdit = new QLineEdit (aGroupBox1); + myWPlaneLineEdit->setReadOnly(true); +#endif + + QLabel *aPolylineLbl = new QLabel(tr("POLYLINE_IMPORT"), aGroupBox1); + + myPolylineSelButton = new QPushButton (aGroupBox1); + myPolylineSelButton->setIcon(image1); + myPolylineEdit = new QLineEdit (aGroupBox1); + myPolylineEdit->setReadOnly(true); + +#ifdef SET_PLANE + aPlaneLayout->addWidget(aPlaneLbl, 1, 0); + aPlaneLayout->addWidget(myPlnSelButton, 1, 1); + aPlaneLayout->addWidget(myWPlaneLineEdit, 1, 2, 1, 2); +#endif + aPlaneLayout->addWidget(aPolylineLbl, 2, 0); + aPlaneLayout->addWidget(myPolylineSelButton, 2, 1); + aPlaneLayout->addWidget(myPolylineEdit, 2, 2, 1, 2); + + aPlaneLayout->setColumnStretch(2, 1); + myCurve = new CurveCreator_Curve( CurveCreator::Dim2d ); myEditorWidget = new CurveCreator_Widget (centralWidget(), myCurve); myAddElementBox = new QGroupBox (tr("POLYLINE_ADD_SECTION"), centralWidget()); @@ -68,6 +128,7 @@ EntityGUI_PolylineDlg::EntityGUI_PolylineDlg layout->setMargin( 0 ); layout->setSpacing( 6 ); + layout->addWidget( aGroupBox1 ); layout->addWidget( myEditorWidget ); layout->addWidget( myAddElementBox ); @@ -99,20 +160,49 @@ void EntityGUI_PolylineDlg::Init() SalomeApp_Application *anApp = myGeomGUI->getApp(); OCCViewer_ViewManager *aViewManager = dynamic_cast (anApp->getViewManager(OCCViewer_Viewer::Type(), true)); + LightApp_SelectionMgr *aSelMgr = myGeomGUI->getApp()->selectionMgr(); - myEditorWidget->setOCCViewer( aViewManager ? aViewManager->getOCCViewer() : 0 ); + myEditorWidget->setOCCViewer(aViewManager ? aViewManager->getOCCViewer() : 0); + // Init the list of local coordinate system + gp_Pnt aPnt(0., 0., 0.); + gp_Dir aDirN(0., 0., 1.); + gp_Dir aDirX(1., 0., 0.); + gp_Ax3 aLCS(aPnt, aDirN, aDirX); + + //add Global CS + myPlnComboBox->addItem(tr("GEOM_GCS"), false); + myWPlaneList.push_back(GEOM::GeomObjPtr()); + myLCSList.push_back(aLCS); + + connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog())); + connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnCancel())); + +#ifdef SET_PLANE + connect(myPlnSelButton, SIGNAL(clicked()), + this, SLOT(SetEditCurrentArgument())); +#endif + connect(myPolylineSelButton, SIGNAL(clicked()), + this, SLOT(SetEditCurrentArgument())); + connect(aSelMgr, SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); connect(myEditorWidget, SIGNAL(subOperationStarted(QWidget*, bool)), this, SLOT(processStartedSubOperation(QWidget*, bool))); connect(myEditorWidget, SIGNAL(subOperationFinished(QWidget*)), this, SLOT(processFinishedSubOperation(QWidget*))); connect(myEditorWidget, SIGNAL(curveModified()), this, SLOT(onUpdatePreview())); +#ifdef SET_PLANE + connect(myPlnComboBox, SIGNAL(activated(int)), + this, SLOT(ActivateLocalCS())); + connect(myPlnButton, SIGNAL(clicked()), + this, SLOT(ActivateLocalCS())); +#endif connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); myAddElementBox->hide(); - + myPolylineSelButton->click(); SelectionIntoArgument(); } @@ -129,7 +219,7 @@ void EntityGUI_PolylineDlg::Clear() } //================================================================================= -// function : createOperation +// function : GetCurveParams // purpose : //================================================================================= void EntityGUI_PolylineDlg::GetCurveParams(GEOM::ListOfListOfDouble &theCoords, @@ -211,18 +301,39 @@ bool EntityGUI_PolylineDlg::execute( ObjectList& objects ) GetCurveParams(aCoords, aNames, aTypes, aCloseds); - // Temporary code: get Working Plane. - GEOM::GEOM_IBasicOperations_var aBasicOp = getGeomEngine()->GetIBasicOperations( getStudyId() ); - GEOM::GEOM_Object_var aWPlane = aBasicOp->MakeMarker( 0,0,0, - 1,0,0, - 0,1,0 ); + // Get Working Plane. + int ind = myPlnComboBox->currentIndex(); - // Perform operation - GEOM::GEOM_Object_var anObj = anOper->MakePolyline2DOnPlane - (aCoords, aNames, aTypes, aCloseds, aWPlane); + if (ind != -1) { + bool isPlane = myPlnComboBox->itemData(ind).toBool(); + GEOM::GEOM_Object_var anObj; - if (!anObj->_is_nil()) { - objects.push_back(anObj._retn()); + // Perform operation + if (isPlane) { + anObj = anOper->MakePolyline2DOnPlane + (aCoords, aNames, aTypes, aCloseds, myWPlaneList.at(ind).get()); + } else { + gp_Ax3 anAxis = myLCSList.at(ind); + GEOM::ListOfDouble aPlane; + + aPlane.length(9); + aPlane[0] = anAxis.Location().X(); + aPlane[1] = anAxis.Location().Y(); + aPlane[2] = anAxis.Location().Z(); + aPlane[3] = anAxis.Direction().X(); + aPlane[4] = anAxis.Direction().Y(); + aPlane[5] = anAxis.Direction().Z(); + aPlane[6] = anAxis.XDirection().X(); + aPlane[7] = anAxis.XDirection().Y(); + aPlane[8] = anAxis.XDirection().Z(); + + anObj = anOper->MakePolyline2D + (aCoords, aNames, aTypes, aCloseds, aPlane); + } + + if (!anObj->_is_nil()) { + objects.push_back(anObj._retn()); + } } return true; @@ -254,6 +365,16 @@ bool EntityGUI_PolylineDlg::ClickOnApply() return true; } +//================================================================================= +// function : ClickOnCancel() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::ClickOnCancel() +{ + myEditorWidget->SetViewer2DMode(false); + GEOMBase_Skeleton::ClickOnCancel(); +} + //================================================================================= // function : processStartedSubOperation // purpose : @@ -287,7 +408,7 @@ void EntityGUI_PolylineDlg::processFinishedSubOperation( QWidget* theWidget ) } //================================================================================= -// function : execute +// function : deleteSelected // purpose : Redirect the delete action to editor widget //================================================================================= void EntityGUI_PolylineDlg::deleteSelected() @@ -310,27 +431,93 @@ bool EntityGUI_PolylineDlg::deleteEnabled() //================================================================================= void EntityGUI_PolylineDlg::SelectionIntoArgument() { -/* - GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_SHAPE ); - TopoDS_Shape aShape; + bool isModified = false; + GEOM::GeomObjPtr aSelectedObject = getSelected(TopAbs_SHAPE); + TopoDS_Shape aShape; - if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) { - if (aShape.ShapeType() == TopAbs_FACE) { - QString aName = GEOMBase::GetName( aSelectedObject.get() ); - myGroup->LineEdit1->setText( aName ); + if (aSelectedObject && GEOMBase::GetShape(aSelectedObject.get(), aShape) && + !aShape.IsNull()) { + QString aName = GEOMBase::GetName(aSelectedObject.get()); - // clear selection - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); - myGeomGUI->getApp()->selectionMgr()->clearSelected(); - connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); + if (myEditCurrentArgument == myPolylineEdit) { + // Import a curve + CurveCreator_Curve *aNewCurve = + new CurveCreator_Curve(CurveCreator::Dim2d); + gp_Ax3 aLocalCS; - myFace = aSelectedObject; + if (CurveCreator_Utils::constructCurve(aShape, aNewCurve, aLocalCS)) { + // Change the current curve be the new one. + myEditorWidget->setCurve(aNewCurve); + delete myCurve; + myCurve = aNewCurve; + isModified = true; + myPolylineEdit->setText(aName); +#ifdef SET_PLANE + AddLocalCS(aSelectedObject.get(), false, aLocalCS); + myWPlaneLineEdit->clear(); + myPlnSelButton->setDown(false); +#endif + myPolylineSelButton->setDown(true); + } else { + // Does nothing, just clears selection. + delete aNewCurve; + } +#ifdef SET_PLANE + } else if (myEditCurrentArgument == myWPlaneLineEdit) { + // Import planar face. + if (aShape.ShapeType() == TopAbs_FACE) { + // Check if the face is planar + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape)); + GeomLib_IsPlanarSurface aPlanarCheck(aSurf, Precision::Confusion()); + + if (aPlanarCheck.IsPlanar()) { + myWPlaneLineEdit->setText(aName); + myPolylineEdit->clear(); + AddLocalCS(aSelectedObject.get(), true, + WPlaneToLCS(aSelectedObject.get())); + isModified = true; + myPlnSelButton->setDown(true); + myPolylineSelButton->setDown(false); + } + } + + if (!isModified) { + myEditCurrentArgument->setText(tr("GEOM_SKETCHER_WPLANE")); + } +#endif } } - displayPreview(true); -*/ + if (!isModified) { + // Does nothing, just clears selection. + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + myGeomGUI->getApp()->selectionMgr()->clearSelected(); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + } +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::SetEditCurrentArgument() +{ + if (sender() == myPlnSelButton) { +#ifdef SET_PLANE + myEditCurrentArgument = myWPlaneLineEdit; + myEditCurrentArgument->setFocus(); + myPlnSelButton->setDown(true); + myPolylineSelButton->setDown(false); +#endif + } else if (sender() == myPolylineSelButton) { + myEditCurrentArgument = myPolylineEdit; + myEditCurrentArgument->setFocus(); +#ifdef SET_PLANE + myPlnSelButton->setDown(false); +#endif + myPolylineSelButton->setDown(true); + } } //================================================================================= @@ -341,7 +528,8 @@ void EntityGUI_PolylineDlg::ActivateThisDialog() { GEOMBase_Skeleton::ActivateThisDialog(); - SelectionIntoArgument(); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); } //================================================================================= @@ -362,3 +550,121 @@ void EntityGUI_PolylineDlg::onUpdatePreview() { displayPreview(true); } + +//================================================================================= +// function : ActivateLocalCS +// purpose : Activate & Fit Working plane +//================================================================================= +void EntityGUI_PolylineDlg::ActivateLocalCS() +{ + const int ind = myPlnComboBox->currentIndex(); + + if (ind == 0) { + // Default plane +#ifdef SET_PLANE + myWPlaneLineEdit->clear(); +#endif + myPolylineEdit->clear(); + } else if (ind > 0) { // Skip 0 as it is default + // Update text on line edits. + QString aName = GEOMBase::GetName(GetActiveWPlane().get()); + bool isPlane = myPlnComboBox->itemData(ind).toBool(); + + if (isPlane) { +#ifdef SET_PLANE + myWPlaneLineEdit->setText(aName); +#endif + myPolylineEdit->clear(); + } else { + myPolylineEdit->setText(aName); +#ifdef SET_PLANE + myWPlaneLineEdit->clear(); +#endif + } + } + + gp_Ax3 anAxis = GetActiveLocalCS(); + + myGeomGUI->SetWorkingPlane(anAxis); + myGeomGUI->ActiveWorkingPlane(); +} + +//================================================================================= +// function : GetActiveLocalCS +// purpose : Get Working plane +//================================================================================= +gp_Ax3 EntityGUI_PolylineDlg::GetActiveLocalCS() +{ + const int ind = myPlnComboBox->currentIndex(); + + return ind >= 0 ? myLCSList.at(ind) : myGeomGUI->GetWorkingPlane(); +} + +//================================================================================= +// function : GetActiveWPlane +// purpose : Get Working plane +//================================================================================= +GEOM::GeomObjPtr EntityGUI_PolylineDlg::GetActiveWPlane() +{ + const int ind = myPlnComboBox->currentIndex(); + + return ind >= 0 ? myWPlaneList.at(ind) : GEOM::GeomObjPtr(); +} + +//================================================================================= +// function : AddLocalCS() +// purpose : Add All Coordinates systems in study +//================================================================================= +void EntityGUI_PolylineDlg::AddLocalCS(GEOM::GeomObjPtr theSelectedObject, + const bool IsPlane, + const gp_Ax3 &theLCS) +{ + QString aName = GEOMBase::GetName(theSelectedObject.get()); + + int index = myPlnComboBox->findText(aName, Qt::MatchExactly); + + if (index == -1) { // If the working plane hasn't been added yet + myWPlaneList.push_back(theSelectedObject); + myLCSList.push_back(theLCS); + myPlnComboBox->addItem(aName, QVariant(IsPlane)); + index = myPlnComboBox->count(); + myPlnComboBox->setCurrentIndex(index - 1); + } else { + myPlnComboBox->setCurrentIndex(index); + } + ActivateLocalCS(); +} + +//================================================================================= +// function : WPlaneToLCS ( aWPlane ) +// purpose : +//================================================================================= +gp_Ax3 EntityGUI_PolylineDlg::WPlaneToLCS(GEOM::GeomObjPtr theGeomObj) +{ + TopoDS_Shape aShape = + GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), theGeomObj.get()); + gp_Ax3 aLCS; + + if (theGeomObj || aShape.IsNull()) { + MESSAGE("CORBA::is_nil(theGeomObj) || aShape.IsNull()") + } + + aLCS.Transform(aShape.Location().Transformation()); + + if (aShape.ShapeType() == TopAbs_FACE) { + GEOM::GEOM_IMeasureOperations_ptr aMeasureOp = + myGeomGUI->GetGeomGen()->GetIMeasureOperations(getStudyId()); + double Ox, Oy, Oz, Zx, Zy, Zz, Xx, Xy, Xz; + + aMeasureOp->GetPosition(theGeomObj.get(), Ox, Oy, Oz, Zx, Zy, Zz, Xx, Xy, Xz); + + if (aMeasureOp->IsDone()) { + gp_Pnt aPnt (Ox, Oy, Oz); + gp_Dir aDirN (Zx, Zy, Zz); + gp_Dir aDirX (Xx, Xy, Xz); + aLCS = gp_Ax3(aPnt, aDirN, aDirX); + } + } + + return aLCS; +} diff --git a/src/EntityGUI/EntityGUI_PolylineDlg.h b/src/EntityGUI/EntityGUI_PolylineDlg.h index 3de683d65..6f7b009a5 100644 --- a/src/EntityGUI/EntityGUI_PolylineDlg.h +++ b/src/EntityGUI/EntityGUI_PolylineDlg.h @@ -26,10 +26,10 @@ #include - class CurveCreator_Curve; class CurveCreator_Widget; class QGroupBox; +class QComboBox; //================================================================================= @@ -84,21 +84,68 @@ private: GEOM::short_array &theTypes, GEOM::ListOfBool &theCloseds); + /** + * This method returns the current local coordinate system. + * + * \return local coordinate system. + */ + gp_Ax3 GetActiveLocalCS(); + + /** + * This method returns the current working plane. Can be null. + * + * \return the current working plane. + */ + GEOM::GeomObjPtr GetActiveWPlane(); + + /** + * This method add a local coordinate system of the selected object. + * + * \param theSelectedObject the selected object. It can be a planar face + * or an inported polyline. + * \param IsPlane true for planar face; false for imported polyline. + * \param theLCS the local coordinate system. + */ + void AddLocalCS(GEOM::GeomObjPtr theSelectedObject, + const bool IsPlane, + const gp_Ax3 &theLCS); + + /** + * This method converts the working plane object into + * the local coordinate system of the polyline. + * + * \param theGeomObj the working plane + * \return the local coordinate system + */ + gp_Ax3 WPlaneToLCS(GEOM::GeomObjPtr theGeomObj); + protected slots: void ClickOnOk(); bool ClickOnApply(); + void ClickOnCancel(); void processStartedSubOperation( QWidget*, bool ); void processFinishedSubOperation( QWidget* ); + void SetEditCurrentArgument(); void SelectionIntoArgument(); void ActivateThisDialog(); void onUpdatePreview(); + void ActivateLocalCS(); private: - CurveCreator_Curve *myCurve; - CurveCreator_Widget *myEditorWidget; - QGroupBox *myAddElementBox; + CurveCreator_Curve *myCurve; + CurveCreator_Widget *myEditorWidget; + QGroupBox *myAddElementBox; + QComboBox *myPlnComboBox; + QPushButton *myPlnButton; + QPushButton *myPlnSelButton; + QPushButton *myPolylineSelButton; + QLineEdit *myWPlaneLineEdit; + QLineEdit *myPolylineEdit; + QLineEdit *myEditCurrentArgument; /* Current LineEdit */ + QList myLCSList; + QList myWPlaneList; }; diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 2e7b31a74..6d2494f0d 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -5597,6 +5597,10 @@ Ignoring units will cause model scaling (as dimensions are supposed to be specif POLYLINE_NAME Polyline + + POLYLINE_IMPORT + Import polyline + POLYLINE_ADD_SECTION Add section