X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROCurveCreator%2FCurveCreator_Utils.cxx;h=7be2d6b379927d604455637c003b95cf18f3bb6d;hb=4e1b53167581be7e084a3d71c075507bc6699c06;hp=e5809e49101c733205e13395d6d6b4eb95ef8fa8;hpb=8db2d905c84a7596e0e3e027ae8e415d5c5166d9;p=modules%2Fhydro.git diff --git a/src/HYDROCurveCreator/CurveCreator_Utils.cxx b/src/HYDROCurveCreator/CurveCreator_Utils.cxx index e5809e49..7be2d6b3 100644 --- a/src/HYDROCurveCreator/CurveCreator_Utils.cxx +++ b/src/HYDROCurveCreator/CurveCreator_Utils.cxx @@ -56,6 +56,8 @@ #include #include +#include +#include #include #include @@ -66,7 +68,8 @@ #include "CurveCreator_ICurve.hxx" const double LOCAL_SELECTION_TOLERANCE = 0.0001; -const int SCENE_PIXEL_TOLERANCE = 10; +const int SCENE_PIXEL_PROJECTION_TOLERANCE = 10; +const int SCENE_PIXEL_POINT_TOLERANCE = 5; //======================================================================= // function : ConvertClickToPoint() @@ -86,7 +89,48 @@ void CurveCreator_Utils::ConvertPointToClick( const gp_Pnt& thePoint, //======================================================================= gp_Pnt CurveCreator_Utils::ConvertClickToPoint( int x, int y, Handle(V3d_View) aView ) { - return GEOMUtils::ConvertClickToPoint( x, y, aView ); + // the 3D point, that is a projection of the pixels to the XYZ view plane + //return GEOMUtils::ConvertClickToPoint( x, y, aView ); + + // we need the projection to the XOY plane + // 1. find a point in the plane of the eye and the normal to the plane + Standard_Real X, Y, Z; + Quantity_Parameter Vx, Vy, Vz; + aView->ConvertWithProj( x, y, X, Y, Z, Vx, Vy, Vz ); + + // 2. build a ray from the point by the normal to the XOY plane and intersect it + // The ray equation is the following : p(x,y,z) = p0(x,y,z) + t*V(x,y,z) + // X,Y,Z - defines p0(x,y,z), Vx,Vy,Vz - defines V(x,y,z) + // p(x,y,z) - is a searched point, t - should to be calculated by the condition of XOY plane + // The system of equations is the following: + // p(x) = p0(x)+t*V(x) + // p(y) = p0(y)+t*V(y) + // p(z) = p0(z)+t*V(z) + // p(z) = 0 + + Standard_Real aXp, aYp, aZp; + //It is not possible to use Precision::Confusion(), because it is e-0.8, but V is sometimes e-6 + Standard_Real aPrec = LOCAL_SELECTION_TOLERANCE; + if ( fabs( Vz ) > aPrec ) { + Standard_Real aT = -Z/Vz; + aXp = X + aT*Vx; + aYp = Y + aT*Vy; + aZp = Z + aT*Vz; + } + else { // Vz = 0 - the eyed plane is orthogonal to Z plane - XOZ, or YOZ + aXp = aYp = aZp = 0; + if ( fabs( Vy ) < aPrec ) // Vy = 0 - the YOZ plane + aYp = Y; + else if ( fabs( Vx ) < aPrec ) // Vx = 0 - the XOZ plane + aXp = X; + } + /*std::cout << "ConvertClickToPoint: " << std::endl + << "XYZ1 = (" << X << ", " << Y << ", " << Z << "); " << std::endl + << "Vxyz = (" << Vx << ", " << Vy << ", " << Vz << "); " << std::endl + << "Resp = (" << aXp << ", " << aYp << ", " << aZp << "); " << std::endl;*/ + + gp_Pnt ResultPoint( aXp, aYp, aZp ); + return ResultPoint; } void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve, @@ -101,40 +145,75 @@ void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve, CurveCreator::SectionType aSectType = theCurve->getSectionType( theISection ); int aPointSize = theCurve->getNbPoints( theISection ); + if ( aPointSize == 0 ) + continue; + bool aSectIsClosed = theCurve->isClosed( theISection ); bool isPolyline = aSectType == CurveCreator::Polyline; + int iPoint = 0; gp_Pnt aPrevPoint, aPoint; - if ( aPointSize == 1 ) { + // filters the curve points to skip equal points + std::vector aPoints; + CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint ); + aPoints.push_back( aPoint ); + aPrevPoint = aPoint; + iPoint++; + for( ; iPoint < aPointSize; iPoint++ ) { CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint ); + if ( !isEqualPoints( aPrevPoint, aPoint ) ) + aPoints.push_back( aPoint ); + aPrevPoint = aPoint; + } + int aNbPoints = aPoints.size(); + + if ( aNbPoints == 1 ) { + aPoint = aPoints.front(); TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); aBuilder.Add( aComp, aVertex ); } - else if ( aPointSize > 1 ) { - Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt (1, aPointSize); - int aHIndex = 1; + else if ( aNbPoints > 1 ) { + Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt(1, aNbPoints); + TColgp_Array1OfVec aTangents(1, aNbPoints); + Handle(TColStd_HArray1OfBoolean) aTangentFlags = new TColStd_HArray1OfBoolean(1, aNbPoints); + gp_Vec aNullVec(0, 0, 0); TopoDS_Edge aPointEdge; TopoDS_Vertex aVertex; - CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint ); + + std::vector::const_iterator aPointIt = aPoints.begin(), aPointLast = aPoints.end(); + aPoint = *aPointIt; + + int aHIndex = 1; aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); aBuilder.Add( aComp, aVertex ); - aHCurvePoints->SetValue(aHIndex++, aPoint); + if ( !isPolyline ) { + aHCurvePoints->SetValue( aHIndex, aPoint ); + aTangents.SetValue( aHIndex, aNullVec ); + aTangentFlags->SetValue( aHIndex, Standard_False ); + aHIndex++; + } + aPrevPoint = aPoint; - iPoint++; - for( ; iPoint < aPointSize; iPoint++ ) { - CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint ); + aPointIt++; + for( ; aPointIt != aPointLast; aPointIt++ ) { + aPoint = *aPointIt; aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); aBuilder.Add( aComp, aVertex ); - aHCurvePoints->SetValue(aHIndex++, aPoint); if ( isPolyline ) { - aPointEdge = BRepBuilderAPI_MakeEdge( aPrevPoint, aPoint ).Edge(); + TopoDS_Edge aPointEdge = BRepBuilderAPI_MakeEdge( aPrevPoint, aPoint ).Edge(); aBuilder.Add( aComp, aPointEdge ); } + else { + aHCurvePoints->SetValue( aHIndex, aPoint ); + aTangents.SetValue( aHIndex, aNullVec ); + aTangentFlags->SetValue( aHIndex, Standard_False ); + aHIndex++; + } aPrevPoint = aPoint; } - if( aSectIsClosed && ( aPointSize > 2 ) ) { - CurveCreator_UtilsICurve::getPoint( theCurve, theISection, 0, aPoint ); + if( aSectIsClosed && ( aNbPoints > 2 ) ) { + aPoint = aPoints.front(); aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); aBuilder.Add( aComp, aVertex ); if ( isPolyline ) { @@ -146,6 +225,14 @@ void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve, // compute BSpline Handle(Geom_BSplineCurve) aBSplineCurve; GeomAPI_Interpolate aGBC(aHCurvePoints, aSectIsClosed, gp::Resolution()); + // correct the spline degree to be as 3 for non-periodic spline if number of points + // less than 3. It is need to have a knot in each spline point. This knots are used + // to found a neighbour points when a new point is inserted between two existing. + if (!aSectIsClosed ) { + if (aHCurvePoints->Length() == 3) + aGBC.Load(aTangents, aTangentFlags); + } + aGBC.Perform(); if ( aGBC.IsDone() ) aBSplineCurve = aGBC.Curve(); @@ -158,26 +245,27 @@ void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve, theShape = aComp; } -class ComparePnt +class CompareSectionToPoint { public: - ComparePnt( const gp_Pnt& thePoint ) : myPoint( thePoint) {}; - ~ComparePnt() {} + CompareSectionToPoint( const int theISection = -1, const int theIPoint = -1 ) + : mySectionId( theISection ), myPointId( theIPoint ) {}; + ~CompareSectionToPoint() {} - bool operator < ( const ComparePnt& theOtherPoint ) const + bool operator < ( const CompareSectionToPoint& theOther ) const { - bool isLess = myPoint.X() < theOtherPoint.myPoint.X(); - if ( !isLess && myPoint.X() == theOtherPoint.myPoint.X() ) { - isLess = myPoint.Y() < theOtherPoint.myPoint.Y(); - if ( !isLess && myPoint.Y() == theOtherPoint.myPoint.Y() ) - isLess = myPoint.Z() < theOtherPoint.myPoint.Z(); - } + bool isLess = mySectionId < theOther.mySectionId; + if ( !isLess && mySectionId == theOther.mySectionId ) + isLess = myPointId < theOther.myPointId; return isLess; } + private: - gp_Pnt myPoint; + int mySectionId; + int myPointId; }; + void CurveCreator_Utils::getSelectedPoints( Handle(AIS_InteractiveContext) theContext, const CurveCreator_ICurve* theCurve, CurveCreator_ICurve::SectionToPointList& thePoints ) @@ -186,7 +274,7 @@ void CurveCreator_Utils::getSelectedPoints( Handle(AIS_InteractiveContext) theCo std::list aSelectedPoints; gp_Pnt aPnt; - std::map aPntMap; + std::map aPointsMap; CurveCreator_ICurve::SectionToPointList aPoints; for ( theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected() ) { @@ -198,15 +286,19 @@ void CurveCreator_Utils::getSelectedPoints( Handle(AIS_InteractiveContext) theCo if ( aVertex.IsNull() ) continue; aPnt = BRep_Tool::Pnt( aVertex ); - if ( aPntMap.find( aPnt ) != aPntMap.end() ) - continue; - aPntMap[aPnt] = 0; CurveCreator_UtilsICurve::findSectionsToPoints( theCurve, aPnt.X(), aPnt.Y(), aPoints ); CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aPoints.begin(), aLast = aPoints.end(); - for ( ; anIt != aLast; anIt++ ) + CompareSectionToPoint aPoint; + for ( ; anIt != aLast; anIt++ ) { + aPoint = CompareSectionToPoint( (*anIt).first, (*anIt).second ); + if ( aPointsMap.find( aPoint ) != aPointsMap.end() ) + continue; + aPointsMap[aPoint] = 0; + thePoints.push_back( *anIt ); + } } } @@ -214,59 +306,55 @@ void CurveCreator_Utils::setSelectedPoints( Handle(AIS_InteractiveContext) theCo const CurveCreator_ICurve* theCurve, const CurveCreator_ICurve::SectionToPointList& thePoints ) { - AIS_ListOfInteractive aDisplayedList; - theContext->DisplayedObjects( aDisplayedList ); - theContext->ClearSelected( Standard_False ); + if ( !theCurve ) + return; - for ( AIS_ListIteratorOfListOfInteractive it( aDisplayedList ); it.More(); it.Next() ) - { - Handle(AIS_InteractiveObject) anAIS = it.Value(); - if ( anAIS.IsNull() ) - continue; - Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast( anAIS ); - if ( anAISShape.IsNull() ) - continue; + Handle(AIS_InteractiveObject) anAIS = theCurve->getAISObject(); + if ( anAIS.IsNull() ) + return; + Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast( anAIS ); + if ( anAISShape.IsNull() ) + return; - //ASL: we convert list of point indices to list of points coordinates - int aSize = thePoints.size(); - std::vector aPntsToSelect( aSize ); - - CurveCreator_ICurve::SectionToPointList::const_iterator - aPIt = thePoints.begin(), aPLast = thePoints.end(); - CurveCreator_ICurve::SectionToPoint aSToPoint; - for( int i=0; aPIt != aPLast; aPIt++, i++ ) - { - gp_Pnt aPntToSelect; - CurveCreator_UtilsICurve::getPoint( theCurve, aPIt->first, aPIt->second, aPntToSelect ); - aPntsToSelect[i] = aPntToSelect; - } + //ASL: we convert list of point indices to list of points coordinates + int aSize = thePoints.size(); + std::vector aPntsToSelect( aSize ); + CurveCreator_ICurve::SectionToPointList::const_iterator + aPIt = thePoints.begin(), aPLast = thePoints.end(); + CurveCreator_ICurve::SectionToPoint aSToPoint; + for( int i=0; aPIt != aPLast; aPIt++, i++ ) + { + gp_Pnt aPntToSelect; + CurveCreator_UtilsICurve::getPoint( theCurve, aPIt->first, aPIt->second, aPntToSelect ); + aPntsToSelect[i] = aPntToSelect; + } - //ASL: we switch off automatic highlight to improve performance of selection - theContext->SetAutomaticHilight( Standard_False ); + theContext->ClearSelected( Standard_False ); + //ASL: we switch off automatic highlight to improve performance of selection + theContext->SetAutomaticHilight( Standard_False ); - Handle_SelectMgr_Selection aSelection = anAISShape->Selection( AIS_Shape::SelectionMode( TopAbs_VERTEX ) ); - for( aSelection->Init(); aSelection->More(); aSelection->Next() ) - { - Handle_SelectBasics_SensitiveEntity aSenEntity = aSelection->Sensitive(); - Handle_Select3D_SensitivePoint aSenPnt = Handle_Select3D_SensitivePoint::DownCast( aSenEntity ); + Handle_SelectMgr_Selection aSelection = anAISShape->Selection( AIS_Shape::SelectionMode( TopAbs_VERTEX ) ); + for( aSelection->Init(); aSelection->More(); aSelection->Next() ) + { + Handle_SelectBasics_SensitiveEntity aSenEntity = aSelection->Sensitive(); + Handle_Select3D_SensitivePoint aSenPnt = Handle_Select3D_SensitivePoint::DownCast( aSenEntity ); - gp_Pnt anOwnerPnt = aSenPnt->Point(); - Handle_SelectMgr_EntityOwner anOwner = Handle_SelectMgr_EntityOwner::DownCast( aSenPnt->OwnerId() ); + gp_Pnt anOwnerPnt = aSenPnt->Point(); + Handle_SelectMgr_EntityOwner anOwner = Handle_SelectMgr_EntityOwner::DownCast( aSenPnt->OwnerId() ); - CurveCreator_ICurve::SectionToPointList::const_iterator anIt = thePoints.begin(), - aLast = thePoints.end(); - bool isFound = false; - for( int i=0; iAddOrRemoveSelected( anOwner, Standard_False ); - break; - } + theContext->AddOrRemoveSelected( anOwner, Standard_False ); + break; } } } @@ -281,14 +369,10 @@ void CurveCreator_Utils::setSelectedPoints( Handle(AIS_InteractiveContext) theCo // function : setLocalPointContext // purpose : Open/close the viewer local context //======================================================================= -//#define USE_GLOBAL_SELECTION -void CurveCreator_Utils::setLocalPointContext( - Handle(AIS_InteractiveContext) theContext, - const bool theOpen ) +void CurveCreator_Utils::setLocalPointContext( const CurveCreator_ICurve* theCurve, + Handle(AIS_InteractiveContext) theContext, + const bool theOpen ) { -#ifdef USE_GLOBAL_SELECTION - return; -#endif if ( !theContext ) return; @@ -298,30 +382,15 @@ void CurveCreator_Utils::setLocalPointContext( theContext->ClearCurrents( false ); theContext->OpenLocalContext( false/*use displayed objects*/, true/*allow shape decomposition*/ ); } - AIS_ListOfInteractive aList; - theContext->DisplayedObjects( aList ); - int aLSize = 0; - for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() ) - aLSize++; - - for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() ) + // load the curve AIS object to the local context with the point selection + Handle(AIS_InteractiveObject) anAIS = theCurve->getAISObject(); + if ( !anAIS.IsNull() ) { - Handle(AIS_InteractiveObject) anAIS = it.Value(); - if ( !anAIS.IsNull() ) + if ( anAIS->IsKind( STANDARD_TYPE( AIS_Shape ) ) ) { - if ( anAIS->IsKind( STANDARD_TYPE( AIS_Shape ) ) ) - { - theContext->Load( anAIS, -1/*selection mode*/, true/*allow decomposition*/ ); - //theContext->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_WIRE ) ); - theContext->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_VERTEX ) ); - } - else if ( anAIS->DynamicType() != STANDARD_TYPE(AIS_Trihedron) ) - { - theContext->Load( anAIS, -1/*selection mode*/, false/*allow decomposition*/ ); - theContext->Activate( anAIS, TopAbs_VERTEX ); - } + theContext->Load( anAIS, -1/*selection mode*/, true/*allow decomposition*/ ); + theContext->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_VERTEX ) ); } - continue; } } else { @@ -330,35 +399,6 @@ void CurveCreator_Utils::setLocalPointContext( } } -/*bool CurveCreator_Utils::getNeighbourPoints( Handle(AIS_InteractiveContext) theContext, - Handle(V3d_View) theView, - const int theX, const int theY, - gp_Pnt& thePoint, gp_Pnt& thePoint1, - gp_Pnt& thePoint2 ) -{ - bool isFoundPoint = false; - if ( theContext.IsNull() ) - return isFoundPoint; - - for ( theContext->InitSelected(); theContext->MoreSelected() && !isFoundPoint; - theContext->NextSelected() ) { - TopoDS_Shape aTShape = theContext->SelectedShape(); - if ( !aTShape.IsNull() && aTShape.ShapeType() == TopAbs_VERTEX ) - continue; - else { - Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner(); - if ( anOwner.IsNull() ) - continue; - const TopLoc_Location& aLocation = anOwner->Location(); - Handle(AIS_InteractiveObject) anAIS = - Handle(AIS_InteractiveObject)::DownCast( anOwner->Selectable() ); - isFoundPoint = CurveCreator_Utils::pointOnObject( theView, anAIS, theX, theY, thePoint, - thePoint1, thePoint2 ); - } - } - return isFoundPoint; -}*/ - bool CurveCreator_Utils::pointOnObject( Handle(V3d_View) theView, Handle(AIS_InteractiveObject) theObject, const int theX, const int theY, @@ -369,78 +409,85 @@ bool CurveCreator_Utils::pointOnObject( Handle(V3d_View) theView, if ( theObject.IsNull() || theView.IsNull() ) return isFullFound; + Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast( theObject ); + if ( aShape.IsNull() ) + return isFullFound; + const TopoDS_Compound& aCompound = TopoDS::Compound( aShape->Shape() ); + if ( aCompound.IsNull() ) + return isFullFound; - gp_Pnt aPoint, aFoundPoint; + gp_Pnt aCurPoint, aCurPoint1, aCurPoint2; + gp_Pnt aFoundPoint, aFoundPnt1, aFoundPnt2; Standard_Real aParameter; - gp_Pnt aPnt1, aPnt2, aFoundPnt1, aFoundPnt2; bool isFound = false; + int aDelta, aMinDelta = 2*SCENE_PIXEL_PROJECTION_TOLERANCE*SCENE_PIXEL_PROJECTION_TOLERANCE; + TopExp_Explorer anExp( aCompound, TopAbs_EDGE ); + for ( ; anExp.More(); anExp.Next()) { - int aDelta, aMinDelta = 2*SCENE_PIXEL_TOLERANCE*SCENE_PIXEL_TOLERANCE; - Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast( theObject ); - if ( !aShape.IsNull() ) { - const TopoDS_Compound& aCompound = TopoDS::Compound( aShape->Shape() ); - if ( !aCompound.IsNull() ) { - TopExp_Explorer anExp( aCompound, TopAbs_EDGE ); - for ( ; anExp.More(); anExp.Next()) - { - const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); - if ( anEdge.IsNull() ) - continue; - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst, aLast ); - if ( aCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) ) { - Handle(Geom_BSplineCurve) aBSplineCurve = Handle(Geom_BSplineCurve)::DownCast( aCurve ); - if ( !aBSplineCurve.IsNull() ) { - isFound = hasProjectPointOnCurve( theView, theX, theY, aBSplineCurve, - aParameter, aDelta ); - if ( isFound ) { - aPoint = aBSplineCurve->Value( aParameter ); - Standard_Integer anI1, anI2; - aBSplineCurve->LocateU( aParameter, LOCAL_SELECTION_TOLERANCE, anI1, anI2 ); - - aPnt1 = aBSplineCurve->Value( aBSplineCurve->Knot( anI1 ) ); - aPnt2 = aBSplineCurve->Value( aBSplineCurve->Knot( anI2 ) ); - } - } - } - else { // usual curve - Handle(Geom_Line) aGLine = Handle(Geom_Line)::DownCast( aCurve ); - if ( !aGLine.IsNull() ) { - isFound = hasProjectPointOnCurve( theView, theX, theY, aGLine, aParameter, - aDelta ); - if ( isFound ) { - aPoint = aGLine->Value( aParameter ); - - TopoDS_Vertex V1, V2; - TopExp::Vertices(anEdge, V1, V2, Standard_True); - if (!V1.IsNull() && !V2.IsNull()) - { - aPnt1 = BRep_Tool::Pnt(V1); - aPnt2 = BRep_Tool::Pnt(V2); - } - gp_Vec aVec1( aPnt1, aPoint ); - gp_Vec aVec2( aPnt2, aPoint ); - double anAngle = aVec1.Angle( aVec2 ); - isFound = fabs( anAngle - M_PI ) < LOCAL_SELECTION_TOLERANCE; - } - } - } - if ( isFound && aMinDelta >= aDelta ) { - isFullFound = true; - aMinDelta = aDelta; - aFoundPnt1 = aPnt1; - aFoundPnt2 = aPnt2; - aFoundPoint = aPoint; - } + const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); + if ( anEdge.IsNull() ) + continue; + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst, aLast ); + if ( aCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) ) { + Handle(Geom_BSplineCurve) aBSplineCurve = + Handle(Geom_BSplineCurve)::DownCast( aCurve ); + if ( !aBSplineCurve.IsNull() ) { + isFound = hasProjectPointOnCurve( theView, theX, theY, aBSplineCurve, + aParameter, aDelta ); + if ( isFound ) { + aCurPoint = aBSplineCurve->Value( aParameter ); + Standard_Integer anI1, anI2; + aBSplineCurve->LocateU( aParameter, LOCAL_SELECTION_TOLERANCE, anI1, anI2 ); + aCurPoint1 = aBSplineCurve->Value( aBSplineCurve->Knot( anI1 ) ); + aCurPoint2 = aBSplineCurve->Value( aBSplineCurve->Knot( anI2 ) ); } } } + else { // a curve built on a polyline edge + Handle(Geom_Line) aGLine = Handle(Geom_Line)::DownCast( aCurve ); + if ( aGLine.IsNull() ) + continue; + isFound = hasProjectPointOnCurve( theView, theX, theY, aGLine, aParameter, + aDelta ); + if ( isFound ) { + aCurPoint = aGLine->Value( aParameter ); + TopoDS_Vertex V1, V2; + TopExp::Vertices( anEdge, V1, V2, Standard_True ); + if ( V1.IsNull() || V2.IsNull() ) + continue; + aCurPoint1 = BRep_Tool::Pnt(V1); + aCurPoint2 = BRep_Tool::Pnt(V2); + + // check that the projected point is on the bounded curve + gp_Vec aVec1( aCurPoint1, aCurPoint ); + gp_Vec aVec2( aCurPoint2, aCurPoint ); + isFound = fabs( aVec1.Angle( aVec2 ) - M_PI ) < LOCAL_SELECTION_TOLERANCE; + } + } + if ( isFound && aMinDelta >= aDelta ) { + aMinDelta = aDelta; + + isFullFound = true; + aFoundPnt1 = aCurPoint1; + aFoundPnt2 = aCurPoint2; + aFoundPoint = aCurPoint; + } } if ( isFullFound ) { - thePoint = aPoint; - thePoint = aFoundPoint; - thePoint1 = aFoundPnt1; - thePoint2 = aFoundPnt2; + int aX, anY, aX1, anY1, aX2, anY2; + int aDelta; + CurveCreator_Utils::ConvertPointToClick( aFoundPoint, theView, aX, anY ); + CurveCreator_Utils::ConvertPointToClick( aFoundPnt1, theView, aX1, anY1 ); + CurveCreator_Utils::ConvertPointToClick( aFoundPnt2, theView, aX2, anY2 ); + + isFullFound = !isEqualPixels( aX, anY, aX1, anY1, SCENE_PIXEL_POINT_TOLERANCE, aDelta ) && + !isEqualPixels( aX, anY, aX2, anY2, SCENE_PIXEL_POINT_TOLERANCE, aDelta ); + if ( isFullFound ) { + thePoint = aFoundPoint; + thePoint1 = aFoundPnt1; + thePoint2 = aFoundPnt2; + } } return isFullFound; } @@ -467,11 +514,24 @@ bool CurveCreator_Utils::hasProjectPointOnCurve( Handle(V3d_View) theView, int aX, anY; CurveCreator_Utils::ConvertPointToClick( aNewPoint, theView, aX, anY ); - int aXDelta = abs( aX - theX ); - int anYDelta = abs( anY - theY ); - theDelta = aXDelta*aXDelta + anYDelta*anYDelta; - isFound = aXDelta < SCENE_PIXEL_TOLERANCE && anYDelta < SCENE_PIXEL_TOLERANCE; + isFound = isEqualPixels( aX, anY, theX, theY, SCENE_PIXEL_PROJECTION_TOLERANCE, theDelta ); } } return isFound; } + +bool CurveCreator_Utils::isEqualPixels( const int theX, const int theY, const int theOtherX, + const int theOtherY, const double theTolerance, int& theDelta ) +{ + int aXDelta = abs( theX - theOtherX ); + int anYDelta = abs( theY - theOtherY ); + + theDelta = aXDelta*aXDelta + anYDelta*anYDelta; + + return aXDelta < theTolerance && anYDelta < theTolerance; +} + +bool CurveCreator_Utils::isEqualPoints( const gp_Pnt& thePoint, const gp_Pnt& theOtherPoint ) +{ + return theOtherPoint.IsEqual( thePoint, LOCAL_SELECTION_TOLERANCE ); +}