From 7a41b78911b40687b327ada02e5cd3927bde2b7d Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 13 May 2014 12:21:25 +0400 Subject: [PATCH] refs #30 - Sketch base GUI: create, draw lines If the second point of a line is on another line, approximate point to belong to this line. --- src/PartSet/PartSet_OperationSketchLine.cpp | 77 ++++++++++++++++++++- src/PartSet/PartSet_OperationSketchLine.h | 16 +++++ src/PartSet/PartSet_Tools.cpp | 54 ++++++++++++++- src/PartSet/PartSet_Tools.h | 26 +++++++ 4 files changed, 169 insertions(+), 4 deletions(-) diff --git a/src/PartSet/PartSet_OperationSketchLine.cpp b/src/PartSet/PartSet_OperationSketchLine.cpp index 2538cfd5f..1b36cb183 100644 --- a/src/PartSet/PartSet_OperationSketchLine.cpp +++ b/src/PartSet/PartSet_OperationSketchLine.cpp @@ -11,9 +11,17 @@ #include #include +#include +#include + +#include + #include #include +#include +#include +#include #ifdef _DEBUG #include @@ -58,6 +66,43 @@ void PartSet_OperationSketchLine::mouseReleased(QMouseEvent* theEvent, Handle(V3 const std::list& theSelected) { gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView); + + if (!theSelected.empty()) { + XGUI_ViewerPrs aPrs = theSelected.front(); + const TopoDS_Shape& aShape = aPrs.shape(); + if (!aShape.IsNull()) { + if (aShape.ShapeType() == TopAbs_VERTEX) { + const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape); + if (!aVertex.IsNull()) + aPoint = BRep_Tool::Pnt(aVertex); + } + else if (aShape.ShapeType() == TopAbs_EDGE) { + boost::shared_ptr aFeature = aPrs.feature(); + if (!aFeature) + return; + double X0, X1, X2, X3; + double Y0, Y1, Y2, Y3; + getLinePoint(aFeature, LINE_ATTR_START, X2, Y2); + getLinePoint(aFeature, LINE_ATTR_END, X3, Y3); + + if (myPointSelectionMode == SM_SecondPoint) { + getLinePoint(feature(), LINE_ATTR_START, X0, Y0); + PartSet_Tools::ConvertTo2D(aPoint, mySketch, theView, X1, Y1); + + double aX, anY; + PartSet_Tools::IntersectLines(X0, X1, X2, X3, Y0, Y1, Y2, Y3, aX, anY); + + setLinePoint(aX, anY, LINE_ATTR_END); + commit(); + emit featureConstructed(feature(), FM_Deactivation); + emit launchOperation(PartSet_OperationSketchLine::Type(), feature()); + return; + } + + } + } + } + switch (myPointSelectionMode) { case SM_FirstPoint: { @@ -113,6 +158,7 @@ void PartSet_OperationSketchLine::startOperation() { PartSet_OperationSketchBase::startOperation(); myPointSelectionMode = !myInitPoint ? SM_FirstPoint : SM_SecondPoint; + emit multiSelectionEnabled(false); } void PartSet_OperationSketchLine::abortOperation() @@ -121,6 +167,12 @@ void PartSet_OperationSketchLine::abortOperation() PartSet_OperationSketchBase::abortOperation(); } +void PartSet_OperationSketchLine::stopOperation() +{ + PartSet_OperationSketchBase::stopOperation(); + emit multiSelectionEnabled(true); +} + boost::shared_ptr PartSet_OperationSketchLine::createFeature() { boost::shared_ptr aNewFeature = ModuleBase_Operation::createFeature(); @@ -141,15 +193,36 @@ boost::shared_ptr PartSet_OperationSketchLine::createFeature() return aNewFeature; } -void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint, - Handle(V3d_View) theView, +void PartSet_OperationSketchLine::getLinePoint(boost::shared_ptr theFeature, + const std::string& theAttribute, + double& theX, double& theY) +{ + if (!theFeature) + return; + boost::shared_ptr aData = theFeature->data(); + boost::shared_ptr aPoint = + boost::dynamic_pointer_cast(aData->attribute(theAttribute)); + theX = aPoint->x(); + theY = aPoint->y(); +} + +void PartSet_OperationSketchLine::setLinePoint(double theX, double theY, const std::string& theAttribute) { boost::shared_ptr aData = feature()->data(); boost::shared_ptr aPoint = boost::dynamic_pointer_cast(aData->attribute(theAttribute)); + aPoint->setValue(theX, theY); +} +void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint, + Handle(V3d_View) theView, + const std::string& theAttribute) +{ double aX, anY; PartSet_Tools::ConvertTo2D(thePoint, mySketch, theView, aX, anY); + boost::shared_ptr aData = feature()->data(); + boost::shared_ptr aPoint = + boost::dynamic_pointer_cast(aData->attribute(theAttribute)); aPoint->setValue(aX, anY); } diff --git a/src/PartSet/PartSet_OperationSketchLine.h b/src/PartSet/PartSet_OperationSketchLine.h index 8dda6b9c6..498f3ca4b 100644 --- a/src/PartSet/PartSet_OperationSketchLine.h +++ b/src/PartSet/PartSet_OperationSketchLine.h @@ -72,6 +72,10 @@ protected: /// Before the feature is aborted, it should be hidden from the viewer virtual void abortOperation(); + /// Virtual method called when operation stopped - committed or aborted. + /// Restore the multi selection state + virtual void stopOperation(); + /// Creates an operation new feature /// In addition to the default realization it appends the created line feature to /// the sketch feature @@ -79,6 +83,18 @@ protected: virtual boost::shared_ptr createFeature(); protected: + /// \brief Get the line point 2d coordinates. + /// \param theFeature the line feature + /// \param theAttribute the start or end attribute of the line + /// \param theX the horizontal coordinate + /// \param theY the vertical coordinate + void getLinePoint(boost::shared_ptr theFeature, const std::string& theAttribute, + double& theX, double& theY); + /// \brief Save the point to the line. + /// \param theX the horizontal coordinate + /// \param theY the vertical coordinate + /// \param theAttribute the start or end attribute of the line + void setLinePoint(double theX, double theY, const std::string& theAttribute); /// \brief Save the point to the line. /// \param thePoint the 3D point in the viewer /// \param theAttribute the start or end attribute of the line diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index 04a41572a..5d97e7002 100644 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -13,12 +13,16 @@ #include #include #include +#include +#include #include #ifdef _DEBUG #include #endif +const double PRECISION_TOLERANCE = 0.000001; + gp_Pnt PartSet_Tools::ConvertClickToPoint(QPoint thePoint, Handle(V3d_View) theView) { if (theView.IsNull()) @@ -80,8 +84,8 @@ void PartSet_Tools::ConvertTo2D(const gp_Pnt& thePoint, boost::shared_ptr(aData->attribute(SKETCH_ATTR_NORM)); gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z()); - double aDen = anEyeVec*aNormalVec; - double aLVec = aDen != 0 ? aVec*aNormalVec/aDen : aVec*aNormalVec; + double aDen = anEyeVec * aNormalVec; + double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX; gp_Vec aDeltaVec = anEyeVec*aLVec; aVec = aVec - aDeltaVec; @@ -89,3 +93,49 @@ void PartSet_Tools::ConvertTo2D(const gp_Pnt& thePoint, boost::shared_ptrx() + aVec.Y() * aX->y() + aVec.Z() * aX->z(); theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z(); } + +void PartSet_Tools::IntersectLines(double theX0, double theX1, double theX2, double theX3, + double theY0, double theY1, double theY2, double theY3, + double& theX, double& theY) +{ + double aV1 = theX1 - theX0, aV2 = theY1 - theY0; + double aW1 = theX3 - theX2, aW2 = theY3 - theY2; + + double aT2 = 0; + if (aV1 != 0 && aV2 != 0) + aT2 = (( theY2 - theY0 )/aV2 - ( theX2 - theX0 )/aV1) / ( aW1/aV1 - aW2/aV2 ); + else + aT2 = DBL_MAX; + + theX = theX2 + aT2*aW1; + theY = theY2 + aT2*aW2; + + // the coordinates of two lines are on the common line + //It is not possible to use Precision::Confusion(), because it is e-0.8, but V is sometimes e-6 + Standard_Real aPrec = PRECISION_TOLERANCE; + if (fabs(theX - theX0) < aPrec && fabs(theY - theY0) < aPrec) { + ProjectPointOnLine(theX2, theX3, theY2, theY3, theX1, theY1, theX, theY); + } +} + +void PartSet_Tools::ProjectPointOnLine(double theX1, double theX2, double theY1, double theY2, + double thePointX, double thePointY, double& theX, double& theY) +{ + //GEOM_Line aLine(gp_Pnt(theX1, theY1), gp_Dir(gp_Vec(gp_Pnt(theX1, theY1), gp_Pnt(theX2, theY2)))); + //GeomAPI_ProjectPointOnCurve aProj(gp_Pnt(thePointX, thePointY)); + /* + Standard_Integer aNbPoint = aProj.NbPoints(); + if (aNbPoint > 0) { + for (Standard_Integer j = 1; j <= aNbPoint && !isFound; j++) { + gp_Pnt aNewPoint = aProj.Point( j ); + theParameter = aProj.Parameter( j ); + + int aX, anY; + CurveCreator_Utils::ConvertPointToClick( aNewPoint, theView, aX, anY ); + + isFound = isEqualPixels( aX, anY, theX, theY, SCENE_PIXEL_PROJECTION_TOLERANCE, theDelta ); + } + } + return isFound; + */ +} \ No newline at end of file diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index 19cdccb2e..419ef4550 100644 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -35,6 +35,32 @@ public: /// \param theY the Y coordinate static void ConvertTo2D(const gp_Pnt& thePoint, boost::shared_ptr theSketch, Handle(V3d_View) theView, double& theX, double& theY); + + /// Returns the point of intersection of the two lines, the first is (v0, v1), the second is (v2, v3), + /// where vi - {xi,yi}. If the v0 is on the second line, the result is a projection of the v1 to this line + /// \param theX0 the horizontal coordinate of 0 point + /// \param theX1 the horizontal coordinate of 1 point + /// \param theX2 the horizontal coordinate of 2 point + /// \param theX3 the horizontal coordinate of 3 point + /// \param theY0 the vertical coordinate of 0 point + /// \param theY1 the vertical coordinate of 1 point + /// \param theY2 the vertical coordinate of 2 point + /// \param theY3 the vertical coordinate of 3 point + /// \param theX the output horizontal coordinate of the intersection point + /// \param theY the outpup vertical coordinate of the intersection point + static void IntersectLines(double theX0, double theX1, double theX2, double theX3, + double theY0, double theY1, double theY2, double theY3, + double& theX, double& theY); + + /// Returns the coordinates of projection of the point to the line + /// \param thePointX the projected point horizontal coordinate + /// \param thePointY the projected point vertictal coordinate + /// \param theX1 the horizontal coordinate of the first line point + /// \param theX2 the horizontal coordinate of the second line point + /// \param theY1 the vertical coordinate of the first line point + /// \param theY2 the vertical coordinate of the second line point + static void ProjectPointOnLine(double theX1, double theX2, double theY1, double theY2, + double thePointX, double thePointY, double& theX, double& theY); }; #endif -- 2.39.2