diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx index ba42fb6f8a..35aada5f86 100644 --- a/src/AIS/AIS_InteractiveContext.cxx +++ b/src/AIS/AIS_InteractiveContext.cxx @@ -2983,10 +2983,11 @@ AIS_StatusOfPick AIS_InteractiveContext::SelectDetected (const AIS_SelectionSche if (theSelScheme == AIS_SelectionScheme_Replace && !myLastPicked.IsNull()) { Graphic3d_Vec2i aMousePos (-1, -1); - if (myMainSel->GetManager().GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point) + gp_Pnt2d aMouseRealPos = myMainSel->GetManager().GetMousePosition(); + if (!Precision::IsInfinite (aMouseRealPos.X()) && + !Precision::IsInfinite (aMouseRealPos.Y())) { - aMousePos.SetValues ((Standard_Integer )myMainSel->GetManager().GetMousePosition().X(), - (Standard_Integer )myMainSel->GetManager().GetMousePosition().Y()); + aMousePos.SetValues ((Standard_Integer )aMouseRealPos.X(), (Standard_Integer )aMouseRealPos.Y()); } if (myLastPicked->HandleMouseClick (aMousePos, Aspect_VKeyMouse_LeftButton, Aspect_VKeyFlags_NONE, false)) { diff --git a/src/AIS/AIS_Manipulator.cxx b/src/AIS/AIS_Manipulator.cxx index 7ff3327b1a..99a003e93b 100644 --- a/src/AIS/AIS_Manipulator.cxx +++ b/src/AIS/AIS_Manipulator.cxx @@ -64,12 +64,12 @@ namespace //! Checks if picking ray can be used for detection. Standard_Boolean isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const { - if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { return Standard_False; } - const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt()); + const gp_Dir aRay = theMgr.GetViewRayDirection(); return !aRay.IsNormal (myPlaneNormal, myAngleTol); } private: diff --git a/src/AIS/AIS_ViewCube.cxx b/src/AIS/AIS_ViewCube.cxx index a1719c6d61..756f6226a3 100644 --- a/src/AIS/AIS_ViewCube.cxx +++ b/src/AIS/AIS_ViewCube.cxx @@ -80,7 +80,7 @@ public: //! Checks if picking ray can be used for detection. bool isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const { - if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { // disallow rectangular selection return false; @@ -89,7 +89,7 @@ public: if (AIS_ViewCubeOwner* anOwner = dynamic_cast<AIS_ViewCubeOwner* >(myOwnerId.get())) { const Standard_Real anAngleToler = 10.0 * M_PI / 180.0; - const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt()); + const gp_Dir aRay = theMgr.GetViewRayDirection(); const gp_Dir aDir = V3d::GetProjAxis (anOwner->MainOrientation()); return !aRay.IsNormal (aDir, anAngleToler); } diff --git a/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx b/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx index cecbca2a78..982a12ddc1 100644 --- a/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx +++ b/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx @@ -48,6 +48,10 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix, const Standard_Integer theYPix, const IVtk_IView::Handle& theView) { + gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix), + static_cast<Standard_Real> (theYPix)); + mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos); + if (myToUpdateTol) { // Compute and set a sensitivity tolerance according to the renderer (viewport). @@ -65,7 +69,6 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix, Standard_Real aX = RealLast(), aY = RealLast(); Standard_Real aVpWidth = RealLast(), aVpHeight = RealLast(); - mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Point); theView->GetCamera (aProj, anOrient, isOrthographic); mySelectingVolumeMgr.SetCamera (aProj, anOrient, isOrthographic); @@ -75,9 +78,7 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix, theView->GetViewport (aX, aY, aVpWidth, aVpHeight); mySelectingVolumeMgr.SetViewport (aX, aY, aVpWidth, aVpHeight); - gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix), - static_cast<Standard_Real> (theYPix)); - mySelectingVolumeMgr.BuildSelectingVolume (aMousePos); + mySelectingVolumeMgr.BuildSelectingVolume(); TraverseSensitives(); } @@ -92,6 +93,13 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXMin, const Standard_Integer theYMax, const IVtk_IView::Handle& theView) { + gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXMin), + static_cast<Standard_Real> (theYMin)); + gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXMax), + static_cast<Standard_Real> (theYMax)); + mySelectingVolumeMgr.InitBoxSelectingVolume (aMinMousePos, + aMaxMousePos); + if (myToUpdateTol) { // Compute and set a sensitivity tolerance according to the renderer (viewport). @@ -109,7 +117,6 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXMin, Standard_Real aX = RealLast(), aY = RealLast(); Standard_Real aVpWidth = RealLast(), aVpHeight = RealLast(); - mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Box); theView->GetCamera (aProj, anOrient, isOrthographic); mySelectingVolumeMgr.SetCamera (aProj, anOrient, isOrthographic); @@ -119,13 +126,7 @@ void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXMin, theView->GetViewport (aX, aY, aVpWidth, aVpHeight); mySelectingVolumeMgr.SetViewport (aX, aY, aVpWidth, aVpHeight); - gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXMin), - static_cast<Standard_Real> (theYMin)); - gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXMax), - static_cast<Standard_Real> (theYMax)); - - mySelectingVolumeMgr.BuildSelectingVolume (aMinMousePos, - aMaxMousePos); + mySelectingVolumeMgr.BuildSelectingVolume(); TraverseSensitives(); } @@ -138,7 +139,15 @@ void IVtkOCC_ViewerSelector::Pick (double** thePoly, const int theNbPoints, const IVtk_IView::Handle& theView) { + // Build TColgp_Array1OfPnt2d from input array of doubles TColgp_Array1OfPnt2d aPolyline (1, theNbPoints); + for (Standard_Integer anIt = 0; anIt < theNbPoints; anIt++) + { + gp_XY aDispPnt = thePoly[anIt][2] != 0 ? gp_XY (thePoly[anIt][0] / thePoly[anIt][2], thePoly[anIt][1] / thePoly[anIt][2]) + : gp_XY (thePoly[anIt][0], thePoly[anIt][1]); + aPolyline.SetValue (anIt + 1, aDispPnt); + } + mySelectingVolumeMgr.InitPolylineSelectingVolume (aPolyline); if (myToUpdateTol) { @@ -151,23 +160,12 @@ void IVtkOCC_ViewerSelector::Pick (double** thePoly, myToUpdateTol = Standard_False; } - // Build TColgp_Array1OfPnt2d from input array of doubles - gp_XYZ aWorldPnt; - - for (Standard_Integer anIt = 0; anIt < theNbPoints; anIt++) - { - gp_XY aDispPnt = thePoly[anIt][2] != 0 ? gp_XY (thePoly[anIt][0] / thePoly[anIt][2], thePoly[anIt][1] / thePoly[anIt][2]) - : gp_XY (thePoly[anIt][0], thePoly[anIt][1]); - aPolyline.SetValue (anIt + 1, aDispPnt); - } - Standard_Integer aWidth = 0, aHeight = 0; Graphic3d_Mat4d aProj, anOrient; Standard_Boolean isOrthographic = Standard_False; Standard_Real aX = RealLast(), aY = RealLast(); Standard_Real aVpWidth = RealLast(), aVpHeight = RealLast(); - mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Polyline); theView->GetCamera (aProj, anOrient, isOrthographic); mySelectingVolumeMgr.SetCamera (aProj, anOrient, isOrthographic); @@ -177,7 +175,7 @@ void IVtkOCC_ViewerSelector::Pick (double** thePoly, theView->GetViewport (aX, aY, aVpWidth, aVpHeight); mySelectingVolumeMgr.SetViewport (aX, aY, aVpWidth, aVpHeight); - mySelectingVolumeMgr.BuildSelectingVolume (aPolyline); + mySelectingVolumeMgr.BuildSelectingVolume(); TraverseSensitives(); } diff --git a/src/MeshVS/MeshVS_SensitiveQuad.cxx b/src/MeshVS/MeshVS_SensitiveQuad.cxx index e12f3f70ce..860e50986d 100644 --- a/src/MeshVS/MeshVS_SensitiveQuad.cxx +++ b/src/MeshVS/MeshVS_SensitiveQuad.cxx @@ -67,7 +67,7 @@ Standard_Boolean MeshVS_SensitiveQuad::Matches (SelectBasics_SelectingVolumeMana { if (!theMgr.IsOverlapAllowed()) // check for inclusion { - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { SelectBasics_PickResult aDummy; return theMgr.Overlaps (myVertices[0], myVertices[1], myVertices[2], Select3D_TOS_INTERIOR, aDummy) diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx index 5376508176..cf168485bd 100644 --- a/src/QABugs/QABugs_19.cxx +++ b/src/QABugs/QABugs_19.cxx @@ -4145,24 +4145,22 @@ static Standard_Integer OCC26195 (Draw_Interpretor& theDI, Standard_Integer theA } SelectMgr_SelectingVolumeManager* aMgr = new SelectMgr_SelectingVolumeManager(); - aMgr->SetActiveSelectionType (theArgNb > 4 ? - SelectMgr_SelectingVolumeManager::Box : SelectMgr_SelectingVolumeManager::Point); + if (theArgNb > 4) + { + aMgr->InitBoxSelectingVolume (aPxPnt1, aPxPnt2); + } + else + { + aMgr->InitPointSelectingVolume (aPxPnt1); + } aMgr->SetCamera (ViewerTest::CurrentView()->Camera()); aMgr->SetPixelTolerance (ViewerTest::GetAISContext()->PixelTolerance()); Standard_Integer aWidth, aHeight; ViewerTest::CurrentView()->View()->Window()->Size (aWidth, aHeight); aMgr->SetWindowSize (aWidth, aHeight); - if (theArgNb > 4) - { - aMgr->BuildSelectingVolume (aPxPnt1, aPxPnt2); - } - else - { - aMgr->BuildSelectingVolume (aPxPnt1); - } + aMgr->BuildSelectingVolume(); + const gp_Pnt* aVerts = aMgr->GetVertices(); - gp_Pnt aNearPnt = aMgr->GetNearPickedPnt(); - gp_Pnt aFarPnt = aMgr->GetFarPickedPnt(); BRepBuilderAPI_MakePolygon aWireBldrs[4]; aWireBldrs[0].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z())); @@ -4202,6 +4200,17 @@ static Standard_Integer OCC26195 (Draw_Interpretor& theDI, Standard_Integer theA aCmp->SetColor (Quantity_NOC_GREEN); ViewerTest::Display ("c", aCmp, Standard_True, Standard_True); + gp_Pnt aNearPnt = aMgr->GetNearPickedPnt(); + gp_Pnt aFarPnt = aMgr->GetFarPickedPnt(); + if (Precision::IsInfinite (aFarPnt.X()) || + Precision::IsInfinite (aFarPnt.Y()) || + Precision::IsInfinite (aFarPnt.Z())) + { + theDI << "Near: " << aNearPnt.X() << " " << aNearPnt.Y() << " " << aNearPnt.Z() << "\n"; + theDI << "Far: infinite point " << "\n"; + return 0; + } + Handle(Geom_CartesianPoint) aPnt1 = new Geom_CartesianPoint (aNearPnt); Handle(Geom_CartesianPoint) aPnt2 = new Geom_CartesianPoint (aFarPnt); diff --git a/src/Select3D/Select3D_SensitiveCircle.cxx b/src/Select3D/Select3D_SensitiveCircle.cxx index df02327e56..fca5dfbfd0 100644 --- a/src/Select3D/Select3D_SensitiveCircle.cxx +++ b/src/Select3D/Select3D_SensitiveCircle.cxx @@ -225,7 +225,7 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume Points3D (anArrayOfPnt); if (!theMgr.IsOverlapAllowed()) { - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { SelectBasics_PickResult aDummy; return theMgr.Overlaps (anArrayOfPnt, mySensType, aDummy); diff --git a/src/Select3D/Select3D_SensitiveGroup.cxx b/src/Select3D/Select3D_SensitiveGroup.cxx index a89fd931bf..e35ffac63f 100644 --- a/src/Select3D/Select3D_SensitiveGroup.cxx +++ b/src/Select3D/Select3D_SensitiveGroup.cxx @@ -193,9 +193,9 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected() Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr, SelectBasics_PickResult& thePickResult) { - const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point + const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point && myMustMatchAll; - const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point + const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point && myToCheckOverlapAll; if (!toMatchAll && !toCheckAll) { diff --git a/src/Select3D/Select3D_SensitivePoly.cxx b/src/Select3D/Select3D_SensitivePoly.cxx index d582fef161..ebce929629 100644 --- a/src/Select3D/Select3D_SensitivePoly.cxx +++ b/src/Select3D/Select3D_SensitivePoly.cxx @@ -254,7 +254,7 @@ Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_Selecting } const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx); - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { SelectBasics_PickResult aDummy; return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), myPolyg.Pnt3d (aSegmentIdx + 1), aDummy); diff --git a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx index 00939c5c07..7da9ba350e 100644 --- a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx +++ b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx @@ -891,7 +891,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_Selecti myDetectedEdgeNode2 = -1; const bool toDetectRange = !myDetectedElemMap.IsNull() || !myDetectedNodeMap.IsNull(); if (myGroups.IsNull() - || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point + || theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Point || !toDetectRange) { if (!matches (theMgr, thePickResult, toDetectRange)) @@ -995,7 +995,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics myDetectedElem = myDetectedNode = aPointIndex; myMinDepthElem = myMinDepthNode = aPickResult.Depth(); } - if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { if (!myDetectedElemMap.IsNull()) { @@ -1046,7 +1046,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics } aResult = Standard_True; if (!myDetectedElemMap.IsNull() - && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { myDetectedElemMap->ChangeMap().Add(aTriIndex); } @@ -1064,7 +1064,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics myMinDepthNode = aPickResult.Depth(); } if (!myDetectedNodeMap.IsNull() - && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]); } @@ -1152,7 +1152,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics return Standard_False; } - if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { if (!myDetectedElemMap.IsNull()) { @@ -1195,7 +1195,7 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics return Standard_False; } - if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { if (!myDetectedElemMap.IsNull()) { diff --git a/src/Select3D/Select3D_SensitiveSegment.cxx b/src/Select3D/Select3D_SensitiveSegment.cxx index c402199ce9..8726d9d943 100644 --- a/src/Select3D/Select3D_SensitiveSegment.cxx +++ b/src/Select3D/Select3D_SensitiveSegment.cxx @@ -45,7 +45,7 @@ Standard_Boolean Select3D_SensitiveSegment::Matches (SelectBasics_SelectingVolum { if (!theMgr.IsOverlapAllowed()) // check for inclusion { - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { return theMgr.Overlaps (myStart, myEnd, thePickResult); } diff --git a/src/Select3D/Select3D_SensitiveSet.cxx b/src/Select3D/Select3D_SensitiveSet.cxx index 3c2b460b1f..d19b216dfd 100644 --- a/src/Select3D/Select3D_SensitiveSet.cxx +++ b/src/Select3D/Select3D_SensitiveSet.cxx @@ -150,7 +150,7 @@ Standard_Boolean Select3D_SensitiveSet::matches (SelectBasics_SelectingVolumeMan Standard_Integer aMatchesNb = -1; - const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point); + const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point); if (toCheckFullInside && isFullInside) { Standard_Integer aSize = myContent.Size(); diff --git a/src/Select3D/Select3D_SensitiveTriangle.cxx b/src/Select3D/Select3D_SensitiveTriangle.cxx index 47291ad68a..f16c2dfb99 100644 --- a/src/Select3D/Select3D_SensitiveTriangle.cxx +++ b/src/Select3D/Select3D_SensitiveTriangle.cxx @@ -50,7 +50,7 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu { if (!theMgr.IsOverlapAllowed()) { - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { SelectBasics_PickResult aDummy; return theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDummy); diff --git a/src/Select3D/Select3D_SensitiveTriangulation.cxx b/src/Select3D/Select3D_SensitiveTriangulation.cxx index 7e2ddfb4f5..f7bbfa61a2 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.cxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.cxx @@ -388,7 +388,7 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_ { const gp_Pnt aSegmPnt1 = myTriangul->Node (myFreeEdges->Value (aPrimitiveIdx * 2 + 1)); const gp_Pnt aSegmPnt2 = myTriangul->Node (myFreeEdges->Value (aPrimitiveIdx * 2 + 2)); - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { SelectBasics_PickResult aDummy; return theMgr.Overlaps (aSegmPnt1, aSegmPnt2, aDummy); @@ -403,7 +403,7 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_ const gp_Pnt aPnt1 = myTriangul->Node (aNode1); const gp_Pnt aPnt2 = myTriangul->Node (aNode2); const gp_Pnt aPnt3 = myTriangul->Node (aNode3); - if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline) + if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline) { SelectBasics_PickResult aDummy; return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, mySensType, aDummy); diff --git a/src/Select3D/Select3D_SensitiveTriangulation.hxx b/src/Select3D/Select3D_SensitiveTriangulation.hxx index dbc8871396..17f5bab650 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.hxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.hxx @@ -25,6 +25,7 @@ #include <SelectMgr_SelectingVolumeManager.hxx> #include <Select3D_SensitiveSet.hxx> +class Poly_Triangle; class Poly_Triangulation; //! A framework to define selection of a sensitive entity made of a set of triangles. diff --git a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx index c846147082..4e065def7b 100644 --- a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx +++ b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx @@ -33,15 +33,7 @@ class SelectBasics_SelectingVolumeManager { public: - //! Available selection types - enum SelectionType { Point, Box, Polyline, Unknown }; - -public: - - SelectBasics_SelectingVolumeManager() - : myActiveSelectionType(Unknown) - { - } + SelectBasics_SelectingVolumeManager() {} virtual ~SelectBasics_SelectingVolumeManager() {} @@ -113,7 +105,15 @@ public: //! correspondingly) onto far view frustum plane virtual gp_Pnt GetFarPickedPnt() const = 0; - //! Return mouse coordinates for Point selection mode. + //! Valid only for point and rectangular selection. + //! Returns view ray direction + virtual gp_Dir GetViewRayDirection() const = 0; + + //! Checks if it is possible to scale current active selecting volume + virtual Standard_Boolean IsScalableActiveVolume() const = 0; + + //! Returns mouse coordinates for Point selection mode. + //! @return infinite point in case of unsupport of mouse position for this active selection volume. virtual gp_Pnt2d GetMousePosition() const = 0; //! Stores plane equation coefficients (in the following form: @@ -122,10 +122,10 @@ public: //! Dumps the content of me into the stream virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const - { (void)theDepth; OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myActiveSelectionType) } - -protected: - SelectionType myActiveSelectionType; //!< Active selection type: point, box or polyline + { + (void )theOStream; + (void )theDepth; + } }; #endif // _SelectBasics_SelectingVolumeManager_HeaderFile diff --git a/src/SelectMgr/FILES b/src/SelectMgr/FILES index 315af35eef..8b457da1d6 100755 --- a/src/SelectMgr/FILES +++ b/src/SelectMgr/FILES @@ -4,6 +4,8 @@ SelectMgr_AndFilter.cxx SelectMgr_AndFilter.hxx SelectMgr_AndOrFilter.cxx SelectMgr_AndOrFilter.hxx +SelectMgr_BaseIntersector.cxx +SelectMgr_BaseIntersector.hxx SelectMgr_BaseFrustum.cxx SelectMgr_BaseFrustum.hxx SelectMgr_BVHThreadPool.cxx @@ -40,6 +42,7 @@ SelectMgr_SelectionImageFiller.cxx SelectMgr_SelectionImageFiller.hxx SelectMgr_SelectionManager.cxx SelectMgr_SelectionManager.hxx +SelectMgr_SelectionType.hxx SelectMgr_SensitiveEntity.cxx SelectMgr_SensitiveEntity.hxx SelectMgr_SensitiveEntitySet.cxx diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index a373ad0224..d90fba5278 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -16,13 +16,13 @@ #include <SelectMgr_BaseFrustum.hxx> #include <Message.hxx> - +#include <SelectMgr_FrustumBuilder.hxx> #include <Standard_Dump.hxx> -IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseFrustum, SelectMgr_BaseIntersector) //======================================================================= -// function : SelectMgr_SelectingVolume +// function : SelectMgr_BaseFrustum // purpose : Creates new selecting volume with pixel toletance set to 2, // orthographic camera and empty frustum builder //======================================================================= @@ -231,32 +231,14 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt1*/, return Standard_False; } -//======================================================================= -// function : DistToGeometryCenter -// purpose : Measures distance between 3d projection of user-picked -// screen point and given point theCOG -//======================================================================= -Standard_Real SelectMgr_BaseFrustum::DistToGeometryCenter (const gp_Pnt& /*theCOG*/) const -{ - return DBL_MAX; -} - -//======================================================================= -// function : DetectedPoint -// purpose : -//======================================================================= -gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const -{ - return gp_Pnt (RealLast(), RealLast(), RealLast()); -} - //======================================================================= //function : DumpJson //purpose : //======================================================================= -void SelectMgr_BaseFrustum::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +void SelectMgr_BaseFrustum::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const { - OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) + OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_BaseFrustum) + OCCT_DUMP_BASE_CLASS (theOStream, theDepth, SelectMgr_BaseIntersector) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPixelTolerance) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsOrthographic) diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index 05e82ebad9..bfb7107f98 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -16,26 +16,14 @@ #ifndef _SelectMgr_BaseFrustum_HeaderFile #define _SelectMgr_BaseFrustum_HeaderFile -#include <gp_GTrsf.hxx> -#include <Graphic3d_Camera.hxx> -#include <Graphic3d_WorldViewProjState.hxx> -#include <Select3D_BndBox3d.hxx> -#include <Select3D_TypeOfSensitivity.hxx> -#include <SelectMgr_FrustumBuilder.hxx> -#include <SelectMgr_VectorTypes.hxx> -#include <SelectMgr_ViewClipRange.hxx> -#include <SelectBasics_PickResult.hxx> -#include <TColgp_Array1OfPnt.hxx> -#include <TColgp_Array1OfPnt2d.hxx> - -#include <Standard_OStream.hxx> +#include <SelectMgr_BaseIntersector.hxx> //! This class is an interface for different types of selecting frustums, //! defining different selection types, like point, box or polyline //! selection. It contains signatures of functions for detection of //! overlap by sensitive entity and initializes some data for building //! the selecting frustum -class SelectMgr_BaseFrustum : public Standard_Transient +class SelectMgr_BaseFrustum : public SelectMgr_BaseIntersector { public: @@ -43,97 +31,71 @@ public: //! orthographic camera and empty frustum builder Standard_EXPORT SelectMgr_BaseFrustum(); + //! Destructor virtual ~SelectMgr_BaseFrustum() {} - //! Return camera definition. - const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } - - //! Passes camera projection and orientation matrices to builder - Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera)& theCamera); - - //! Passes camera projection and orientation matrices to builder - Standard_EXPORT void SetCamera (const Graphic3d_Mat4d& theProjection, - const Graphic3d_Mat4d& theWorldView, - const Standard_Boolean theIsOrthographic, - const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState()); - - //! @return current camera projection transformation common for all selecting volumes - Standard_EXPORT const Graphic3d_Mat4d& ProjectionMatrix() const; - - //! @return current camera world view transformation common for all selecting volumes - Standard_EXPORT const Graphic3d_Mat4d& WorldViewMatrix() const; - - //! @return current camera world view projection transformation state - Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const; - - Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTol); - - Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, - const Standard_Integer theHeight); - - Standard_EXPORT void WindowSize (Standard_Integer& theWidth, - Standard_Integer& theHeight) const; - - //! Passes viewport parameters to builder - Standard_EXPORT void SetViewport (const Standard_Real theX, - const Standard_Real theY, - const Standard_Real theWidth, - const Standard_Real theHeight); - //! Nullifies the builder created in the constructor and copies the pointer given Standard_EXPORT void SetBuilder (const Handle(SelectMgr_FrustumBuilder)& theBuilder); + //! Return camera definition. + virtual const Handle(Graphic3d_Camera)& Camera() const Standard_OVERRIDE { return myCamera; } - //! Builds volume according to the point and given pixel tolerance - virtual void Build (const gp_Pnt2d& /*thePoint*/) {} + //! Passes camera projection and orientation matrices to builder + Standard_EXPORT virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera) Standard_OVERRIDE; - //! Builds volume according to the selected rectangle - virtual void Build (const gp_Pnt2d& /*theMinPt*/, - const gp_Pnt2d& /*theMaxPt*/) {} + //! Passes camera projection and orientation matrices to builder + Standard_EXPORT virtual void SetCamera (const Graphic3d_Mat4d& theProjection, + const Graphic3d_Mat4d& theWorldView, + const Standard_Boolean theIsOrthographic, + const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState()) Standard_OVERRIDE; - //! Builds volume according to the triangle given - virtual void Build (const gp_Pnt2d& /*theP1*/, - const gp_Pnt2d& /*theP2*/, - const gp_Pnt2d& /*theP3*/) {} + //! @return current camera projection transformation common for all selecting volumes + Standard_EXPORT virtual const Graphic3d_Mat4d& ProjectionMatrix() const Standard_OVERRIDE; + + //! @return current camera world view transformation common for all selecting volumes + Standard_EXPORT virtual const Graphic3d_Mat4d& WorldViewMatrix() const Standard_OVERRIDE; + + //! @return current camera world view projection transformation state + Standard_EXPORT virtual const Graphic3d_WorldViewProjState& WorldViewProjState() const Standard_OVERRIDE; + + Standard_EXPORT virtual void SetPixelTolerance (const Standard_Integer theTol) Standard_OVERRIDE; + + Standard_EXPORT virtual void SetWindowSize (const Standard_Integer theWidth, + const Standard_Integer theHeight) Standard_OVERRIDE; + + Standard_EXPORT virtual void WindowSize (Standard_Integer& theWidth, + Standard_Integer& theHeight) const Standard_OVERRIDE; + + //! Passes viewport parameters to builder + Standard_EXPORT virtual void SetViewport (const Standard_Real theX, + const Standard_Real theY, + const Standard_Real theWidth, + const Standard_Real theHeight) Standard_OVERRIDE; - //! Builds selecting volumes set according to polyline points - virtual void Build (const TColgp_Array1OfPnt2d& /*thePoints*/) {} - //! IMPORTANT: Scaling makes sense only for frustum built on a single point! - //! Note that this method does not perform any checks on type of the frustum. - //! Returns a copy of the frustum resized according to the scale factor given - //! and transforms it using the matrix given. - //! There are no default parameters, but in case if: - //! - transformation only is needed: @theScaleFactor must be initialized as any negative value; - //! - scale only is needed: @theTrsf must be set to gp_Identity. - virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer /*theScaleFactor*/, - const gp_GTrsf& /*theTrsf*/) const - { - return NULL; - } //! SAT intersection test between defined volume and given axis-aligned box Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, const SelectMgr_Vec3& theBoxMax, const SelectMgr_ViewClipRange& theClipRange, - SelectBasics_PickResult& thePickResult) const; + SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; //! Returns true if selecting volume is overlapped by axis-aligned bounding box //! with minimum corner at point theMinPt and maximum at point theMaxPt Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, const SelectMgr_Vec3& theBoxMax, - Standard_Boolean* theInside = NULL) const; + Standard_Boolean* theInside = NULL) const Standard_OVERRIDE; //! Intersection test between defined volume and given point Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, const SelectMgr_ViewClipRange& theClipRange, - SelectBasics_PickResult& thePickResult) const; + SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; //! Intersection test between defined volume and given point //! Does not perform depth calculation, so this method is defined as //! helper function for inclusion test. Therefore, its implementation //! makes sense only for rectangular frustum with box selection mode activated. - Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) const; + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) const Standard_OVERRIDE; //! SAT intersection test between defined volume and given ordered set of points, //! representing line segments. The test may be considered of interior part or @@ -141,13 +103,13 @@ public: Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, const SelectMgr_ViewClipRange& theClipRange, - SelectBasics_PickResult& thePickResult) const; + SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; //! Checks if line segment overlaps selecting frustum Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, const SelectMgr_ViewClipRange& theClipRange, - SelectBasics_PickResult& thePickResult) const; + SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; //! SAT intersection test between defined volume and given triangle. The test may //! be considered of interior part or boundary line defined by triangle vertices @@ -157,26 +119,12 @@ public: const gp_Pnt& thePt3, Select3D_TypeOfSensitivity theSensType, const SelectMgr_ViewClipRange& theClipRange, - SelectBasics_PickResult& thePickResult) const; - - //! Measures distance between 3d projection of user-picked - //! screen point and given point theCOG - Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const; - - Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const; - - //! Stores plane equation coefficients (in the following form: - //! Ax + By + Cz + D = 0) to the given vector - virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const - { - thePlaneEquations.Clear(); - return; - } + SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; //! Dumps the content of me into the stream - Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; - DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,Standard_Transient) + DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseFrustum, SelectMgr_BaseIntersector) protected: Standard_Integer myPixelTolerance; //!< Pixel tolerance diff --git a/src/SelectMgr/SelectMgr_BaseIntersector.cxx b/src/SelectMgr/SelectMgr_BaseIntersector.cxx new file mode 100644 index 0000000000..4552ca1752 --- /dev/null +++ b/src/SelectMgr/SelectMgr_BaseIntersector.cxx @@ -0,0 +1,276 @@ +// Copyright (c) 2021 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include <SelectMgr_BaseIntersector.hxx> + +#include <Graphic3d_Camera.hxx> + +IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseIntersector, Standard_Transient) + +//======================================================================= +// function : ScaleAndTransform +// purpose : +//======================================================================= +Handle(SelectMgr_BaseIntersector) SelectMgr_BaseIntersector::ScaleAndTransform (const Standard_Integer, + const gp_GTrsf&, + const Handle(SelectMgr_FrustumBuilder)&) const +{ + return NULL; +} + +//======================================================================= +// function : Camera +// purpose : +//======================================================================= +const Handle(Graphic3d_Camera)& SelectMgr_BaseIntersector::Camera() const +{ + static const Handle(Graphic3d_Camera) anEmptyCamera; + return anEmptyCamera; +} + +//======================================================================= +// function : SetCamera +// purpose : +//======================================================================= +void SelectMgr_BaseIntersector::SetCamera (const Handle(Graphic3d_Camera)&) +{ +} + +//======================================================================= +// function : SetCamera +// purpose : +//======================================================================= +void SelectMgr_BaseIntersector::SetCamera (const Graphic3d_Mat4d&, + const Graphic3d_Mat4d&, + const Standard_Boolean, + const Graphic3d_WorldViewProjState&) +{ +} + +//======================================================================= +// function : ProjectionMatrix +// purpose : +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_BaseIntersector::ProjectionMatrix() const +{ + static const Graphic3d_Mat4d anEmptyMatrix; + return anEmptyMatrix; +} + +//======================================================================= +// function : WorldViewMatrix +// purpose : +//======================================================================= +const Graphic3d_Mat4d& SelectMgr_BaseIntersector::WorldViewMatrix() const +{ + static const Graphic3d_Mat4d anEmptyMatrix; + return anEmptyMatrix; +} + +//======================================================================= +// function : WorldViewProjState +// purpose : +//======================================================================= +const Graphic3d_WorldViewProjState& SelectMgr_BaseIntersector::WorldViewProjState() const +{ + static const Graphic3d_WorldViewProjState anEmptyState; + return anEmptyState; +} + +//======================================================================= +// function : SetPixelTolerance +// purpose : +//======================================================================= +void SelectMgr_BaseIntersector::SetPixelTolerance (const Standard_Integer) +{ +} + +//======================================================================= +// function : WindowSize +// purpose : +//======================================================================= +void SelectMgr_BaseIntersector::WindowSize (Standard_Integer&, + Standard_Integer&) const +{ +} + +//======================================================================= +// function : SetWindowSize +// purpose : +//======================================================================= +void SelectMgr_BaseIntersector::SetWindowSize (const Standard_Integer, + const Standard_Integer) +{ +} + +//======================================================================= +// function : SetViewport +// purpose : +//======================================================================= +void SelectMgr_BaseIntersector::SetViewport (const Standard_Real, + const Standard_Real, + const Standard_Real, + const Standard_Real) +{ +} + +//======================================================================= +// function : GetNearPnt +// purpose : +//======================================================================= +const gp_Pnt& SelectMgr_BaseIntersector::GetNearPnt() const +{ + static const gp_Pnt anEmptyPnt; + return anEmptyPnt; +} + +//======================================================================= +// function : GetFarPnt +// purpose : +//======================================================================= +const gp_Pnt& SelectMgr_BaseIntersector::GetFarPnt() const +{ + static const gp_Pnt anEmptyPnt(RealLast(), RealLast(), RealLast()); + return anEmptyPnt; +} + +//======================================================================= +// function : GetViewRayDirection +// purpose : +//======================================================================= +const gp_Dir& SelectMgr_BaseIntersector::GetViewRayDirection() const +{ + static const gp_Dir anEmptyDir; + return anEmptyDir; +} + +//======================================================================= +// function : GetMousePosition +// purpose : +//======================================================================= +const gp_Pnt2d& SelectMgr_BaseIntersector::GetMousePosition() const +{ + static const gp_Pnt2d aPnt(RealLast(), RealLast()); + return aPnt; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const SelectMgr_Vec3&, + const SelectMgr_Vec3&, + const SelectMgr_ViewClipRange&, + SelectBasics_PickResult&) const +{ + return Standard_False; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const SelectMgr_Vec3&, + const SelectMgr_Vec3&, + Standard_Boolean*) const +{ + return Standard_False; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt&, + const SelectMgr_ViewClipRange&, + SelectBasics_PickResult&) const +{ + return Standard_False; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt& thePnt) const +{ + (void )thePnt; + return Standard_False; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const TColgp_Array1OfPnt&, + Select3D_TypeOfSensitivity, + const SelectMgr_ViewClipRange&, + SelectBasics_PickResult&) const +{ + return Standard_False; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt&, + const gp_Pnt&, + const gp_Pnt&, + Select3D_TypeOfSensitivity, + const SelectMgr_ViewClipRange&, + SelectBasics_PickResult&) const +{ + return Standard_False; +} + +//======================================================================= +// function : Overlaps +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_BaseIntersector::Overlaps (const gp_Pnt&, + const gp_Pnt&, + const SelectMgr_ViewClipRange&, + SelectBasics_PickResult&) const +{ + return Standard_False; +} + +//======================================================================= +// function : DistToGeometryCenter +// purpose : +//======================================================================= +Standard_Real SelectMgr_BaseIntersector::DistToGeometryCenter (const gp_Pnt&) const +{ + return RealLast(); +} + +//======================================================================= +// function : DetectedPoint +// purpose : +//======================================================================= +gp_Pnt SelectMgr_BaseIntersector::DetectedPoint (const Standard_Real) const +{ + return gp_Pnt(RealLast(), RealLast(), RealLast()); +} + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void SelectMgr_BaseIntersector::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) + + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySelectionType) +} diff --git a/src/SelectMgr/SelectMgr_BaseIntersector.hxx b/src/SelectMgr/SelectMgr_BaseIntersector.hxx new file mode 100644 index 0000000000..ef6e238c36 --- /dev/null +++ b/src/SelectMgr/SelectMgr_BaseIntersector.hxx @@ -0,0 +1,222 @@ +// Copyright (c) 2021 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _SelectMgr_BaseIntersector_HeaderFile +#define _SelectMgr_BaseIntersector_HeaderFile + +#include <gp_GTrsf.hxx> +#include <Graphic3d_Mat4d.hxx> +#include <Graphic3d_WorldViewProjState.hxx> +#include <NCollection_Vector.hxx> +#include <Select3D_TypeOfSensitivity.hxx> +#include <SelectBasics_PickResult.hxx> +#include <SelectMgr_SelectionType.hxx> +#include <SelectMgr_VectorTypes.hxx> +#include <TColgp_Array1OfPnt2d.hxx> +#include <TColgp_Array1OfPnt.hxx> + +class Graphic3d_Camera; +class SelectMgr_FrustumBuilder; +class SelectMgr_ViewClipRange; + +//! This class is an interface for different types of selecting intersector, +//! defining different selection types, like point, box or polyline +//! selection. It contains signatures of functions for detection of +//! overlap by sensitive entity and initializes some data for building +//! the selecting intersector +class SelectMgr_BaseIntersector : public Standard_Transient +{ +public: + + //! Creates new empty selecting volume + SelectMgr_BaseIntersector() + : mySelectionType (SelectMgr_SelectionType_Unknown) + {} + + //! Destructor + virtual ~SelectMgr_BaseIntersector() {} + + //! Builds intersector according to internal parameters + virtual void Build() {} + + //! Returns selection type of this intersector + SelectMgr_SelectionType GetSelectionType() const { return mySelectionType; } + +public: + + //! Checks if it is possible to scale this intersector. + //! @return false for the base class. + virtual Standard_Boolean IsScalable() const { return Standard_False; } + + //! Sets pixel tolerance. + //! It makes sense only for scalable intersectors (built on a single point). + //! This method does nothing for the base class. + Standard_EXPORT virtual void SetPixelTolerance (const Standard_Integer theTol); + + //! IMPORTANT: Scaling makes sense only for scalable intersectors (built on a single point)! + //! Note that this method does not perform any checks on type of the frustum. + //! Returns a copy of the frustum resized according to the scale factor given + //! and transforms it using the matrix given. + //! There are no default parameters, but in case if: + //! - transformation only is needed: @theScaleFactor must be initialized as any negative value; + //! - scale only is needed: @theTrsf must be set to gp_Identity. + //! Builder is an optional argument that represents corresponding settings for re-constructing transformed + //! frustum from scratch. Can be null if reconstruction is not expected furthermore. + //! This method does nothing for the base class. + Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const; + +public: + + //! Returns camera definition. + //! This method returns empty camera for the base class. + Standard_EXPORT virtual const Handle(Graphic3d_Camera)& Camera() const; + + //! Sets camera projection and orientation matrices. + //! This method does nothing for the base class. + Standard_EXPORT virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera); + + //! Sets camera projection and orientation matrices. + //! This method does nothing for the base class. + Standard_EXPORT virtual void SetCamera (const Graphic3d_Mat4d& theProjection, + const Graphic3d_Mat4d& theWorldView, + const Standard_Boolean theIsOrthographic, + const Graphic3d_WorldViewProjState& theWVPState = Graphic3d_WorldViewProjState()); + + //! Returns current camera projection transformation. + //! This method returns empty matrix for the base class. + Standard_EXPORT virtual const Graphic3d_Mat4d& ProjectionMatrix() const; + + //! Returns current camera world view transformation. + //! This method returns empty matrix for the base class. + Standard_EXPORT virtual const Graphic3d_Mat4d& WorldViewMatrix() const; + + //! Returns current camera world view projection transformation state. + //! This method returns empty matrix for the base class. + Standard_EXPORT virtual const Graphic3d_WorldViewProjState& WorldViewProjState() const; + + //! Returns current window size. + //! This method doesn't set any output values for the base class. + Standard_EXPORT virtual void WindowSize (Standard_Integer& theWidth, + Standard_Integer& theHeight) const; + + //! Sets current window size. + //! This method does nothing for the base class. + Standard_EXPORT virtual void SetWindowSize (const Standard_Integer theWidth, + const Standard_Integer theHeight); + + //! Sets viewport parameters. + //! This method does nothing for the base class. + Standard_EXPORT virtual void SetViewport (const Standard_Real theX, + const Standard_Real theY, + const Standard_Real theWidth, + const Standard_Real theHeight); + + //! Returns near point of intersector. + //! This method returns zero point for the base class. + Standard_EXPORT virtual const gp_Pnt& GetNearPnt() const; + + //! Returns far point of intersector. + //! This method returns zero point for the base class. + Standard_EXPORT virtual const gp_Pnt& GetFarPnt() const; + + //! Returns direction ray of intersector. + //! This method returns zero direction for the base class. + Standard_EXPORT virtual const gp_Dir& GetViewRayDirection() const; + + //! Returns current mouse coordinates. + //! This method returns infinite point for the base class. + Standard_EXPORT virtual const gp_Pnt2d& GetMousePosition() const; + + //! Stores plane equation coefficients (in the following form: + //! Ax + By + Cz + D = 0) to the given vector. + //! This method only clears input vector for the base class. + virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const + { + thePlaneEquations.Clear(); + } + +public: + + //! SAT intersection test between defined volume and given axis-aligned box + Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, + const SelectMgr_ViewClipRange& theClipRange, + SelectBasics_PickResult& thePickResult) const; + + //! Returns true if selecting volume is overlapped by axis-aligned bounding box + //! with minimum corner at point theMinPt and maximum at point theMaxPt + Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, + Standard_Boolean* theInside = NULL) const; + + //! Intersection test between defined volume and given point + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, + const SelectMgr_ViewClipRange& theClipRange, + SelectBasics_PickResult& thePickResult) const; + + //! Intersection test between defined volume and given point + //! Does not perform depth calculation, so this method is defined as + //! helper function for inclusion test. Therefore, its implementation + //! makes sense only for rectangular frustum with box selection mode activated. + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) const; + + //! SAT intersection test between defined volume and given ordered set of points, + //! representing line segments. The test may be considered of interior part or + //! boundary line defined by segments depending on given sensitivity type + Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, + Select3D_TypeOfSensitivity theSensType, + const SelectMgr_ViewClipRange& theClipRange, + SelectBasics_PickResult& thePickResult) const; + + //! Checks if line segment overlaps selecting frustum + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + const SelectMgr_ViewClipRange& theClipRange, + SelectBasics_PickResult& thePickResult) const; + + //! SAT intersection test between defined volume and given triangle. The test may + //! be considered of interior part or boundary line defined by triangle vertices + //! depending on given sensitivity type + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, + const gp_Pnt& thePt2, + const gp_Pnt& thePt3, + Select3D_TypeOfSensitivity theSensType, + const SelectMgr_ViewClipRange& theClipRange, + SelectBasics_PickResult& thePickResult) const; + +public: + + //! Measures distance between 3d projection of user-picked + //! screen point and given point theCOG. + //! It makes sense only for intersectors built on a single point. + //! This method returns infinite value for the base class. + Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const; + + //! Calculates the point on a view ray that was detected during the run of selection algo by given depth. + //! It makes sense only for intersectors built on a single point. + //! This method returns infinite point for the base class. + Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const; + + //! Dumps the content of me into the stream + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; + + DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseIntersector,Standard_Transient) + +protected: + + SelectMgr_SelectionType mySelectionType; +}; + +#endif // _SelectMgr_BaseIntersector_HeaderFile diff --git a/src/SelectMgr/SelectMgr_Frustum.hxx b/src/SelectMgr/SelectMgr_Frustum.hxx index b2bcdecf83..52a97c5e9d 100644 --- a/src/SelectMgr/SelectMgr_Frustum.hxx +++ b/src/SelectMgr/SelectMgr_Frustum.hxx @@ -16,13 +16,7 @@ #ifndef _SelectMgr_Frustum_HeaderFile #define _SelectMgr_Frustum_HeaderFile -#include <BVH_Box.hxx> -#include <gp_Pnt.hxx> -#include <gp_Vec.hxx> -#include <gp_XYZ.hxx> #include <SelectMgr_BaseFrustum.hxx> -#include <TColgp_HArray1OfPnt.hxx> -#include <TColgp_Array1OfPnt2d.hxx> //! This is an internal class containing representation of rectangular selecting frustum, created in case //! of point and box selection, and algorithms for overlap detection between selecting diff --git a/src/SelectMgr/SelectMgr_Frustum.lxx b/src/SelectMgr/SelectMgr_Frustum.lxx index 248a9c258c..fabfd004e9 100644 --- a/src/SelectMgr/SelectMgr_Frustum.lxx +++ b/src/SelectMgr/SelectMgr_Frustum.lxx @@ -16,6 +16,7 @@ #include <NCollection_Vector.hxx> #include <Poly_Array1OfTriangle.hxx> #include <Standard_Assert.hxx> +#include <SelectMgr_FrustumBuilder.hxx> // ======================================================================= // function : isSeparated diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index 61a0743b85..27ee456421 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -13,10 +13,22 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include <SelectMgr_RectangularFrustum.hxx> + +#include <BVH_Tools.hxx> #include <NCollection_Vector.hxx> #include <Poly_Array1OfTriangle.hxx> +#include <SelectMgr_FrustumBuilder.hxx> +#include <SelectMgr_ViewClipRange.hxx> -#include <SelectMgr_RectangularFrustum.hxx> +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +SelectMgr_RectangularFrustum::SelectMgr_RectangularFrustum() + : myScale(1.0) +{ +} // ======================================================================= // function : segmentSegmentDistance @@ -204,56 +216,6 @@ namespace // Far theNormals[5] = -theNormals[4]; } - - // ======================================================================= - // function : rayBoxIntersection - // purpose : Computes an intersection of ray with box - // Returns distances to the first (or 0.0 if the ray origin is inside the box) and second intersection - // If the ray has no intersection with the box returns DBL_MAX - // ======================================================================= - Bnd_Range rayBoxIntersection (const gp_Ax1& theRay, const gp_Pnt& theBoxMin, const gp_Pnt& theBoxMax) - { - Standard_Real aTimeMinX = -DBL_MAX; - Standard_Real aTimeMinY = -DBL_MAX; - Standard_Real aTimeMinZ = -DBL_MAX; - Standard_Real aTimeMaxX = DBL_MAX; - Standard_Real aTimeMaxY = DBL_MAX; - Standard_Real aTimeMaxZ = DBL_MAX; - - Standard_Real aTime1; - Standard_Real aTime2; - - if (Abs (theRay.Direction().X()) > DBL_EPSILON) - { - aTime1 = (theBoxMin.X() - theRay.Location().X()) / theRay.Direction().X(); - aTime2 = (theBoxMax.X() - theRay.Location().X()) / theRay.Direction().X(); - - aTimeMinX = Min (aTime1, aTime2); - aTimeMaxX = Max (aTime1, aTime2); - } - if (Abs (theRay.Direction().Y()) > DBL_EPSILON) - { - aTime1 = (theBoxMin.Y() - theRay.Location().Y()) / theRay.Direction().Y(); - aTime2 = (theBoxMax.Y() - theRay.Location().Y()) / theRay.Direction().Y(); - - aTimeMinY = Min (aTime1, aTime2); - aTimeMaxY = Max (aTime1, aTime2); - } - if (Abs (theRay.Direction().Z()) > DBL_EPSILON) - { - aTime1 = (theBoxMin.Z() - theRay.Location().Z()) / theRay.Direction().Z(); - aTime2 = (theBoxMax.Z() - theRay.Location().Z()) / theRay.Direction().Z(); - - aTimeMinZ = Min (aTime1, aTime2); - aTimeMaxZ = Max (aTime1, aTime2); - } - - Standard_Real aTimeMin = Max (aTimeMinX, Max (aTimeMinY, aTimeMinZ)); - Standard_Real aTimeMax = Min (aTimeMaxX, Min (aTimeMaxY, aTimeMaxZ)); - - return aTimeMin > aTimeMax || aTimeMax < 0.0 ? Bnd_Range (DBL_MAX, DBL_MAX) - : Bnd_Range (Max (aTimeMin, 0.0), aTimeMax); - } } // ======================================================================= @@ -316,52 +278,63 @@ void SelectMgr_RectangularFrustum::cacheVertexProjections (SelectMgr_Rectangular } // ======================================================================= -// function : Build -// purpose : Build volume according to the point and given pixel -// tolerance +// function : Init +// purpose : // ======================================================================= -void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint) +void SelectMgr_RectangularFrustum::Init (const gp_Pnt2d &thePoint) { - myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0); - myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0); - myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ(); - myMousePos = thePoint; + mySelectionType = SelectMgr_SelectionType_Point; + mySelRectangle.SetMousePos (thePoint); +} - gp_Pnt2d aMinPnt (thePoint.X() - myPixelTolerance * 0.5, - thePoint.Y() - myPixelTolerance * 0.5); - gp_Pnt2d aMaxPnt (thePoint.X() + myPixelTolerance * 0.5, - thePoint.Y() + myPixelTolerance * 0.5); - - // calculate base frustum characteristics: vertices and edge directions - computeFrustum (aMinPnt, aMaxPnt, myBuilder, myVertices, myEdgeDirs); - - // compute frustum normals - computeNormals (myEdgeDirs, myPlanes); - - // compute vertices projections onto frustum normals and - // {i, j, k} vectors and store them to corresponding class fields - cacheVertexProjections (this); - - myScale = 1.0; +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void SelectMgr_RectangularFrustum::Init (const gp_Pnt2d& theMinPnt, + const gp_Pnt2d& theMaxPnt) +{ + mySelectionType = SelectMgr_SelectionType_Box; + mySelRectangle.SetMinPnt (theMinPnt); + mySelRectangle.SetMaxPnt (theMaxPnt); } // ======================================================================= // function : Build -// purpose : Build volume according to the selected rectangle +// purpose : // ======================================================================= -void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt, - const gp_Pnt2d& theMaxPnt) +void SelectMgr_RectangularFrustum::Build() { - myNearPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5, - (theMinPnt.Y() + theMaxPnt.Y()) * 0.5, - 0.0); - myFarPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5, - (theMinPnt.Y() + theMaxPnt.Y()) * 0.5, - 1.0); + Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Build() should be called after selection frustum initialization"); + gp_Pnt2d aMinPnt, aMaxPnt; + if (mySelectionType == SelectMgr_SelectionType_Point) + { + const gp_Pnt2d& aMousePos = mySelRectangle.MousePos(); + myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (aMousePos.X(), aMousePos.Y(), 0.0); + myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (aMousePos.X(), aMousePos.Y(), 1.0); + + aMinPnt.SetCoord (aMousePos.X() - myPixelTolerance * 0.5, + aMousePos.Y() - myPixelTolerance * 0.5); + aMaxPnt.SetCoord (aMousePos.X() + myPixelTolerance * 0.5, + aMousePos.Y() + myPixelTolerance * 0.5); + } + else + { + aMinPnt = mySelRectangle.MinPnt(); + aMaxPnt = mySelRectangle.MaxPnt(); + myNearPickedPnt = myBuilder->ProjectPntOnViewPlane ((aMinPnt.X() + aMaxPnt.X()) * 0.5, + (aMinPnt.Y() + aMaxPnt.Y()) * 0.5, + 0.0); + myFarPickedPnt = myBuilder->ProjectPntOnViewPlane ((aMinPnt.X() + aMaxPnt.X()) * 0.5, + (aMinPnt.Y() + aMaxPnt.Y()) * 0.5, + 1.0); + } + myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ(); // calculate base frustum characteristics: vertices and edge directions - computeFrustum (theMinPnt, theMaxPnt, myBuilder, myVertices, myEdgeDirs); + computeFrustum (aMinPnt, aMaxPnt, myBuilder, myVertices, myEdgeDirs); // compute frustum normals computeNormals (myEdgeDirs, myPlanes); @@ -384,9 +357,13 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt, // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. // ======================================================================= -Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor, - const gp_GTrsf& theTrsf) const +Handle(SelectMgr_BaseIntersector) SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const { + Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::ScaleAndTransform() should be called after selection frustum initialization"); + Standard_ASSERT_RAISE (theScaleFactor > 0, "Error! Pixel tolerance for selection should be greater than zero"); @@ -395,7 +372,10 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c const Standard_Boolean isToTrsf = theTrsf.Form() != gp_Identity; if (!isToScale && !isToTrsf) + { + aRes->SetBuilder (theBuilder); return aRes; + } aRes->myIsOrthographic = myIsOrthographic; const SelectMgr_RectangularFrustum* aRef = this; @@ -406,10 +386,11 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c aRes->myFarPickedPnt = myFarPickedPnt; aRes->myViewRayDir = myViewRayDir; - const gp_Pnt2d aMinPnt (myMousePos.X() - theScaleFactor * 0.5, - myMousePos.Y() - theScaleFactor * 0.5); - const gp_Pnt2d aMaxPnt (myMousePos.X() + theScaleFactor * 0.5, - myMousePos.Y() + theScaleFactor * 0.5); + const gp_Pnt2d& aMousePos = mySelRectangle.MousePos(); + const gp_Pnt2d aMinPnt (aMousePos.X() - theScaleFactor * 0.5, + aMousePos.Y() - theScaleFactor * 0.5); + const gp_Pnt2d aMaxPnt (aMousePos.X() + theScaleFactor * 0.5, + aMousePos.Y() + theScaleFactor * 0.5); // recompute base frustum characteristics from scratch computeFrustum (aMinPnt, aMaxPnt, myBuilder, aRes->myVertices, aRes->myEdgeDirs); @@ -460,11 +441,21 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (c cacheVertexProjections (aRes.get()); - aRes->myMousePos = myMousePos; - + aRes->mySelectionType = mySelectionType; + aRes->mySelRectangle = mySelRectangle; + aRes->SetBuilder (theBuilder); return aRes; } +// ======================================================================= +// function : IsScalable +// purpose : +// ======================================================================= +Standard_Boolean SelectMgr_RectangularFrustum::IsScalable() const +{ + return mySelectionType == SelectMgr_SelectionType_Point; +} + // ======================================================================= // function : Overlaps // purpose : Returns true if selecting volume is overlapped by @@ -475,6 +466,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t const SelectMgr_Vec3& theBoxMax, Standard_Boolean* theInside) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + return hasOverlap (theBoxMin, theBoxMax, theInside); } @@ -488,18 +482,17 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + if (!hasOverlap (theBoxMin, theBoxMax)) return Standard_False; - gp_Ax1 aRay (myNearPickedPnt, myViewRayDir); - Bnd_Range aRange = rayBoxIntersection (aRay, - gp_Pnt (theBoxMin.x(), theBoxMin.y(), theBoxMin.z()), - gp_Pnt (theBoxMax.x(), theBoxMax.y(), theBoxMax.z())); - Standard_Real aDepth = 0.0; - aRange.GetMin (aDepth); - - if (aDepth == DBL_MAX) + BVH_Ray<Standard_Real, 3> aRay(SelectMgr_Vec3(myNearPickedPnt.X(), myNearPickedPnt.Y(), myNearPickedPnt.Z()), + SelectMgr_Vec3(myViewRayDir.X(), myViewRayDir.Y(), myViewRayDir.Z())); + Standard_Real aTimeEnter, aTimeLeave; + if (!BVH_Tools<Standard_Real, 3>::RayBoxIntersection (aRay, theBoxMin, theBoxMax, aTimeEnter, aTimeLeave)) { gp_Pnt aNearestPnt (RealLast(), RealLast(), RealLast()); aNearestPnt.SetX (Max (Min (myNearPickedPnt.X(), theBoxMax.x()), theBoxMin.x())); @@ -511,6 +504,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t return !theClipRange.IsClipped (thePickResult.Depth()); } + Bnd_Range aRange(Max (aTimeEnter, 0.0), aTimeLeave); + aRange.GetMin (aDepth); + if (!theClipRange.GetNearestDepth (aRange, aDepth)) { return Standard_False; @@ -529,6 +525,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt, const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + if (!hasOverlap (thePnt)) return Standard_False; @@ -547,6 +546,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt, // ======================================================================= Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + return hasOverlap (thePnt); } @@ -559,6 +561,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + if (!hasOverlap (thePnt1, thePnt2)) return Standard_False; @@ -579,6 +584,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPn const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + if (theSensType == Select3D_TOS_BOUNDARY) { Standard_Integer aMatchingSegmentsNb = -1; @@ -637,6 +645,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization"); + if (theSensType == Select3D_TOS_BOUNDARY) { const gp_Pnt aPntsArrayBuf[4] = { thePnt1, thePnt2, thePnt3, thePnt1 }; @@ -727,6 +738,19 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, return !theClipRange.IsClipped (thePickResult.Depth()); } +// ======================================================================= +// function : GetMousePosition +// purpose : +// ======================================================================= +const gp_Pnt2d& SelectMgr_RectangularFrustum::GetMousePosition() const +{ + if (mySelectionType == SelectMgr_SelectionType_Point) + { + return mySelRectangle.MousePos(); + } + return base_type::GetMousePosition(); +} + // ======================================================================= // function : DistToGeometryCenter // purpose : Measures distance between 3d projection of user-picked @@ -734,6 +758,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, // ======================================================================= Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box, + "Error! SelectMgr_RectangularFrustum::DistToGeometryCenter() should be called after selection frustum initialization"); + return theCOG.Distance (myNearPickedPnt) * myScale; } @@ -744,6 +771,8 @@ Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& // ======================================================================= gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const { + Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point, + "SelectMgr_RectangularFrustum::DetectedPoint() should be called only for Point selection type"); return myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * theDepth / myScale; } @@ -780,7 +809,8 @@ void SelectMgr_RectangularFrustum::DumpJson (Standard_OStream& theOStream, Stand OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myNearPickedPnt) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myFarPickedPnt) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myViewRayDir) - OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myMousePos) + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelRectangle.MinPnt()) + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelRectangle.MaxPnt()) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myScale) } diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index d2d41157b1..4d88c1dac5 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -33,14 +33,46 @@ class SelectMgr_RectangularFrustum : public SelectMgr_Frustum<4> { public: - SelectMgr_RectangularFrustum() : myScale (1.0) {}; + //! Auxiliary structure to define selection primitive (point or box) + //! In case of point selection min and max points are identical. + struct SelectionRectangle + { + SelectionRectangle() + : myMinPnt(gp_Pnt2d(RealLast(), RealLast())), + myMaxPnt(gp_Pnt2d(RealLast(), RealLast())) {} - //! Builds volume according to the point and given pixel tolerance - Standard_EXPORT virtual void Build (const gp_Pnt2d& thePoint) Standard_OVERRIDE; + const gp_Pnt2d& MousePos() const { return myMinPnt; } + void SetMousePos (const gp_Pnt2d& thePos) { myMinPnt = thePos; myMaxPnt = thePos; } - //! Builds volume according to the selected rectangle - Standard_EXPORT virtual void Build (const gp_Pnt2d& theMinPnt, - const gp_Pnt2d& theMaxPnt) Standard_OVERRIDE; + const gp_Pnt2d& MinPnt() const { return myMinPnt; } + void SetMinPnt (const gp_Pnt2d& theMinPnt) { myMinPnt = theMinPnt; } + + const gp_Pnt2d& MaxPnt() const { return myMaxPnt; } + void SetMaxPnt (const gp_Pnt2d& theMaxPnt) { myMaxPnt = theMaxPnt; } + + private: + + gp_Pnt2d myMinPnt; + gp_Pnt2d myMaxPnt; + }; + + //! Creates rectangular selecting frustum. + Standard_EXPORT SelectMgr_RectangularFrustum(); + + //! Initializes volume according to the point and given pixel tolerance + Standard_EXPORT void Init (const gp_Pnt2d& thePoint); + + //! Initializes volume according to the selected rectangle + Standard_EXPORT void Init (const gp_Pnt2d& theMinPnt, + const gp_Pnt2d& theMaxPnt); + + //! Builds volume according to internal parameters. + //! NOTE: it should be called after Init() method + Standard_EXPORT virtual void Build() Standard_OVERRIDE; + + //! Checks if it is possible to scale this frustum. + //! It is true for frustum built on a single point. + Standard_EXPORT virtual Standard_Boolean IsScalable() const Standard_OVERRIDE; //! IMPORTANT: Scaling makes sense only for frustum built on a single point! //! Note that this method does not perform any checks on type of the frustum. @@ -49,9 +81,11 @@ public: //! There are no default parameters, but in case if: //! - transformation only is needed: @theScaleFactor must be initialized as any negative value; //! - scale only is needed: @theTrsf must be set to gp_Identity. - Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScaleFactor, - const gp_GTrsf& theTrsf) const Standard_OVERRIDE; - + //! Builder is an optional argument that represents corresponding settings for re-constructing transformed + //! frustum from scratch. Can be null if reconstruction is not expected furthermore. + Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const Standard_OVERRIDE; // SAT Tests for different objects @@ -100,30 +134,31 @@ public: SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; //! Measures distance between 3d projection of user-picked - //! screen point and given point theCOG + //! screen point and given point theCOG. + //! It makes sense only for frustums built on a single point. Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const Standard_OVERRIDE; //! Calculates the point on a view ray that was detected during the run of selection algo by given depth Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE; //! A set of helper functions that return rectangular selecting frustum data - inline const gp_Pnt* GetVertices() const { return myVertices; } + const gp_Pnt* GetVertices() const { return myVertices; } //! Returns projection of 2d mouse picked point or projection //! of center of 2d rectangle (for point and rectangular selection //! correspondingly) onto near view frustum plane - inline const gp_Pnt& GetNearPnt() const { return myNearPickedPnt; } + virtual const gp_Pnt& GetNearPnt() const Standard_OVERRIDE { return myNearPickedPnt; } //! Returns projection of 2d mouse picked point or projection //! of center of 2d rectangle (for point and rectangular selection //! correspondingly) onto far view frustum plane - inline const gp_Pnt& GetFarPnt() const { return myFarPickedPnt; } + virtual const gp_Pnt& GetFarPnt() const Standard_OVERRIDE { return myFarPickedPnt; } - //! Return view ray direction. - const gp_Dir& GetViewRayDirection() const { return myViewRayDir; } + //! Returns view ray direction. + virtual const gp_Dir& GetViewRayDirection() const Standard_OVERRIDE { return myViewRayDir; } - //! Return mouse coordinates. - const gp_Pnt2d& GetMousePosition() const { return myMousePos; } + //! Returns current mouse coordinates. + Standard_EXPORT virtual const gp_Pnt2d& GetMousePosition() const Standard_OVERRIDE; //! Stores plane equation coefficients (in the following form: //! Ax + By + Cz + D = 0) to the given vector @@ -154,10 +189,10 @@ private: private: + SelectionRectangle mySelRectangle; //!< parameters for selection by point or box (it is used to build frustum) gp_Pnt myNearPickedPnt; //!< 3d projection of user-picked selection point onto near view plane gp_Pnt myFarPickedPnt; //!< 3d projection of user-picked selection point onto far view plane - gp_Dir myViewRayDir; - gp_Pnt2d myMousePos; //!< Mouse coordinates + gp_Dir myViewRayDir; //!< view ray direction Standard_Real myScale; //!< Scale factor of applied transformation, if there was any }; diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index 3df0a5b92f..b7ef91848b 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -14,22 +14,22 @@ // commercial license or contractual agreement. #include <SelectMgr_SelectingVolumeManager.hxx> + +#include <Graphic3d_SequenceOfHClipPlane.hxx> +#include <SelectMgr_RectangularFrustum.hxx> +#include <SelectMgr_TriangularFrustumSet.hxx> + +#include <BVH_Tools.hxx> #include <Standard_Dump.hxx> //======================================================================= // function : SelectMgr_SelectingVolumeManager // purpose : Creates instances of all available selecting volume types //======================================================================= -SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums) +SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager() +: myActiveSelectingVolume (NULL), + myToAllowOverlap (Standard_False) { - myActiveSelectionType = Unknown; - myToAllowOverlap = Standard_False; - - if (theToAllocateFrustums) - { - mySelectingVolumes[Frustum] = new SelectMgr_RectangularFrustum(); - mySelectingVolumes[FrustumSet] = new SelectMgr_TriangularFrustumSet(); - } } //======================================================================= @@ -51,16 +51,14 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTrans const gp_GTrsf& theTrsf, const Handle(SelectMgr_FrustumBuilder)& theBuilder) const { - SelectMgr_SelectingVolumeManager aMgr (Standard_False); - - if (myActiveSelectionType == Unknown) + SelectMgr_SelectingVolumeManager aMgr; + if (myActiveSelectingVolume.IsNull()) + { return aMgr; + } - aMgr.myActiveSelectionType = myActiveSelectionType; - aMgr.mySelectingVolumes[myActiveSelectionType / 2] - = mySelectingVolumes[myActiveSelectionType / 2]->ScaleAndTransform (theScaleFactor, theTrsf); + aMgr.myActiveSelectingVolume = myActiveSelectingVolume->ScaleAndTransform (theScaleFactor, theTrsf, theBuilder); aMgr.myToAllowOverlap = myToAllowOverlap; - aMgr.mySelectingVolumes[myActiveSelectionType / 2]->SetBuilder (theBuilder); aMgr.myViewClipPlanes = myViewClipPlanes; aMgr.myObjectClipPlanes = myObjectClipPlanes; aMgr.myViewClipRange = myViewClipRange; @@ -74,29 +72,36 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTrans //======================================================================= Standard_Integer SelectMgr_SelectingVolumeManager::GetActiveSelectionType() const { - return myActiveSelectionType; + if (myActiveSelectingVolume.IsNull()) + { + return SelectMgr_SelectionType_Unknown; + } + return myActiveSelectingVolume->GetSelectionType(); } //======================================================================= -// function : SetActiveSelectionType +// function : Camera // purpose : //======================================================================= -void SelectMgr_SelectingVolumeManager::SetActiveSelectionType (const SelectionType& theType) +const Handle(Graphic3d_Camera)& SelectMgr_SelectingVolumeManager::Camera() const { - myActiveSelectionType = theType; + if (myActiveSelectingVolume.IsNull()) + { + static const Handle(Graphic3d_Camera) anEmptyCamera; + return anEmptyCamera; + } + return myActiveSelectingVolume->Camera(); } //======================================================================= // function : SetCamera -// purpose : Updates camera projection and orientation matrices in all -// selecting volumes +// purpose : //======================================================================= void SelectMgr_SelectingVolumeManager::SetCamera (const Handle(Graphic3d_Camera) theCamera) { - for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) - { - mySelectingVolumes[anIdx]->SetCamera (theCamera); - } + Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::SetCamera() should be called after initialization of selection volume "); + myActiveSelectingVolume->SetCamera (theCamera); } //======================================================================= @@ -109,10 +114,9 @@ void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProj const Standard_Boolean theIsOrthographic, const Graphic3d_WorldViewProjState& theWVPState) { - for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) - { - mySelectingVolumes[anIdx]->SetCamera (theProjection, theWorldView, theIsOrthographic, theWVPState); - } + Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::SetCamera() should be called after initialization of selection volume "); + myActiveSelectingVolume->SetCamera (theProjection, theWorldView, theIsOrthographic, theWVPState); } //======================================================================= @@ -122,7 +126,12 @@ void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProj //======================================================================= const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::ProjectionMatrix() const { - return mySelectingVolumes[Frustum]->ProjectionMatrix(); + if (myActiveSelectingVolume.IsNull()) + { + static const Graphic3d_Mat4d anEmptyMatrix; + return anEmptyMatrix; + } + return myActiveSelectingVolume->ProjectionMatrix(); } //======================================================================= @@ -132,7 +141,12 @@ const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::ProjectionMatrix() cons //======================================================================= const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::WorldViewMatrix() const { - return mySelectingVolumes[Frustum]->WorldViewMatrix(); + if (myActiveSelectingVolume.IsNull()) + { + static const Graphic3d_Mat4d anEmptyMatrix; + return anEmptyMatrix; + } + return myActiveSelectingVolume->WorldViewMatrix(); } //======================================================================= @@ -142,7 +156,12 @@ const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::WorldViewMatrix() const //======================================================================= const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewProjState() const { - return mySelectingVolumes[Frustum]->WorldViewProjState(); + if (myActiveSelectingVolume.IsNull()) + { + static const Graphic3d_WorldViewProjState anEmptyState; + return anEmptyState; + } + return myActiveSelectingVolume->WorldViewProjState(); } //======================================================================= @@ -151,7 +170,23 @@ const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewP //======================================================================= void SelectMgr_SelectingVolumeManager::WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight) const { - mySelectingVolumes[Frustum]->WindowSize (theWidth, theHeight); + if (myActiveSelectingVolume.IsNull()) + { + return; + } + myActiveSelectingVolume->WindowSize (theWidth, theHeight); +} + +//======================================================================= +// function : SetWindowSize +// purpose : Updates window size in all selecting volumes +//======================================================================= +void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth, + const Standard_Integer theHeight) +{ + Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::SetWindowSize() should be called after initialization of selection volume "); + myActiveSelectingVolume->SetWindowSize (theWidth, theHeight); } //======================================================================= @@ -163,23 +198,9 @@ void SelectMgr_SelectingVolumeManager::SetViewport (const Standard_Real theX, const Standard_Real theWidth, const Standard_Real theHeight) { - for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) - { - mySelectingVolumes[anIdx]->SetViewport (theX, theY, theWidth, theHeight); - } -} - -//======================================================================= -// function : SetWindowSize -// purpose : Updates window size in all selecting volumes -//======================================================================= -void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth, - const Standard_Integer theHeight) -{ - for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) - { - mySelectingVolumes[anIdx]->SetWindowSize (theWidth, theHeight); - } + Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::SetViewport() should be called after initialization of selection volume "); + myActiveSelectingVolume->SetViewport (theX, theY, theWidth, theHeight); } //======================================================================= @@ -188,49 +209,107 @@ void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer the //======================================================================= void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance) { - for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) + Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::SetPixelTolerance() should be called after initialization of selection volume "); + myActiveSelectingVolume->SetPixelTolerance (theTolerance); +} + +//======================================================================= +// function : InitPointSelectingVolume +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::InitPointSelectingVolume (const gp_Pnt2d& thePoint) +{ + Handle(SelectMgr_RectangularFrustum) aPntVolume = Handle(SelectMgr_RectangularFrustum)::DownCast(myActiveSelectingVolume); + if (aPntVolume.IsNull()) { - mySelectingVolumes[anIdx]->SetPixelTolerance (theTolerance); + aPntVolume = new SelectMgr_RectangularFrustum(); } + aPntVolume->Init (thePoint); + myActiveSelectingVolume = aPntVolume; +} + +//======================================================================= +// function : InitBoxSelectingVolume +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::InitBoxSelectingVolume (const gp_Pnt2d& theMinPt, + const gp_Pnt2d& theMaxPt) +{ + Handle(SelectMgr_RectangularFrustum) aBoxVolume = Handle(SelectMgr_RectangularFrustum)::DownCast(myActiveSelectingVolume); + if (aBoxVolume.IsNull()) + { + aBoxVolume = new SelectMgr_RectangularFrustum(); + } + aBoxVolume->Init (theMinPt, theMaxPt); + myActiveSelectingVolume = aBoxVolume; +} + +//======================================================================= +// function : InitPolylineSelectingVolume +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::InitPolylineSelectingVolume (const TColgp_Array1OfPnt2d& thePoints) +{ + Handle(SelectMgr_TriangularFrustumSet) aPolylineVolume = Handle(SelectMgr_TriangularFrustumSet)::DownCast(myActiveSelectingVolume); + if (aPolylineVolume.IsNull()) + { + aPolylineVolume = new SelectMgr_TriangularFrustumSet(); + } + aPolylineVolume->Init (thePoints); + myActiveSelectingVolume = aPolylineVolume; + aPolylineVolume->SetAllowOverlapDetection (IsOverlapAllowed()); +} + +//======================================================================= +// function : InitSelectingVolume +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::InitSelectingVolume(const Handle(SelectMgr_BaseIntersector)& theVolume) +{ + myActiveSelectingVolume = theVolume; } //======================================================================= // function : BuildSelectingVolume -// purpose : Builds rectangular selecting frustum for point selection +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::BuildSelectingVolume() +{ + Standard_ASSERT_RAISE (!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::BuildSelectingVolume() should be called after initialization of active selection volume."); + myActiveSelectingVolume->Build(); +} + +//======================================================================= +// function : BuildSelectingVolume +// purpose : //======================================================================= void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& thePoint) { - if (myActiveSelectionType != Point) - return; - - mySelectingVolumes[Frustum]->Build (thePoint); + InitPointSelectingVolume (thePoint); + myActiveSelectingVolume->Build(); } //======================================================================= // function : BuildSelectingVolume -// purpose : Builds rectangular selecting frustum for box selection +// purpose : //======================================================================= void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& theMinPt, const gp_Pnt2d& theMaxPt) { - if (myActiveSelectionType != Box) - return; - - mySelectingVolumes[Frustum]->Build (theMinPt, theMaxPt); + InitBoxSelectingVolume (theMinPt, theMaxPt); + myActiveSelectingVolume->Build(); } //======================================================================= // function : BuildSelectingVolume -// purpose : Builds set of triangular selecting frustums for polyline -// selection +// purpose : //======================================================================= void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints) { - if (myActiveSelectionType != Polyline) - return; - - mySelectingVolumes[FrustumSet]->Build (thePoints); - Handle(SelectMgr_TriangularFrustumSet)::DownCast (mySelectingVolumes[FrustumSet])->SetAllowOverlapDetection (IsOverlapAllowed()); + InitPolylineSelectingVolume (thePoints); + myActiveSelectingVolume->Build(); } //======================================================================= @@ -242,10 +321,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec const SelectMgr_Vec3& theBoxMax, SelectBasics_PickResult& thePickResult) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, myViewClipRange, thePickResult); + return myActiveSelectingVolume->Overlaps (theBoxMin, theBoxMax, myViewClipRange, thePickResult); } //======================================================================= @@ -256,10 +337,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec const SelectMgr_Vec3& theBoxMax, Standard_Boolean* theInside) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theInside); + return myActiveSelectingVolume->Overlaps (theBoxMin, theBoxMax, theInside); } //======================================================================= @@ -269,10 +352,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt, SelectBasics_PickResult& thePickResult) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt, myViewClipRange, thePickResult); + return myActiveSelectingVolume->Overlaps (thePnt, myViewClipRange, thePickResult); } //======================================================================= @@ -281,10 +366,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePn //======================================================================= Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt); + return myActiveSelectingVolume->Overlaps (thePnt); } //======================================================================= @@ -298,11 +385,13 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp Standard_Integer theSensType, SelectBasics_PickResult& thePickResult) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts->Array1(), (Select3D_TypeOfSensitivity)theSensType, - myViewClipRange, thePickResult); + return myActiveSelectingVolume->Overlaps (theArrayOfPnts->Array1(), (Select3D_TypeOfSensitivity)theSensType, + myViewClipRange, thePickResult); } //======================================================================= @@ -316,11 +405,13 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const TColgp_Array1 Standard_Integer theSensType, SelectBasics_PickResult& thePickResult) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts, (Select3D_TypeOfSensitivity)theSensType, - myViewClipRange, thePickResult); + return myActiveSelectingVolume->Overlaps (theArrayOfPnts, (Select3D_TypeOfSensitivity)theSensType, + myViewClipRange, thePickResult); } //======================================================================= @@ -331,10 +422,12 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt const gp_Pnt& thePt2, SelectBasics_PickResult& thePickResult) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1, thePt2, myViewClipRange, thePickResult); + return myActiveSelectingVolume->Overlaps (thePt1, thePt2, myViewClipRange, thePickResult); } //======================================================================= @@ -350,11 +443,13 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt Standard_Integer theSensType, SelectBasics_PickResult& thePickResult) const { - if (myActiveSelectionType == Unknown) + if (myActiveSelectingVolume.IsNull()) + { return Standard_False; + } - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1, thePt2, thePt3, (Select3D_TypeOfSensitivity)theSensType, - myViewClipRange, thePickResult); + return myActiveSelectingVolume->Overlaps (thePt1, thePt2, thePt3, (Select3D_TypeOfSensitivity)theSensType, + myViewClipRange, thePickResult); } //======================================================================= @@ -364,10 +459,11 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt //======================================================================= Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_Pnt& theCOG) const { - if (myActiveSelectionType == Unknown) - return Standard_False; - - return mySelectingVolumes[myActiveSelectionType / 2]->DistToGeometryCenter (theCOG); + if (myActiveSelectingVolume.IsNull()) + { + return RealLast(); + } + return myActiveSelectingVolume->DistToGeometryCenter (theCOG); } // ======================================================================= @@ -378,12 +474,9 @@ Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_P // ======================================================================= gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const { - if (myActiveSelectionType != Point) - { - throw Standard_ProgramError("SelectMgr_SelectingVolumeManager::DetectedPoint() should be called only for Point selection type"); - } - - return mySelectingVolumes[Frustum]->DetectedPoint (theDepth); + Standard_ASSERT_RAISE(!myActiveSelectingVolume.IsNull(), + "SelectMgr_SelectingVolumeManager::DetectedPoint() should be called after initialization of selection volume"); + return myActiveSelectingVolume->DetectedPoint (theDepth); } //======================================================================= @@ -403,7 +496,7 @@ void SelectMgr_SelectingVolumeManager::AllowOverlapDetection (const Standard_Boo //======================================================================= Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const { - return myToAllowOverlap || myActiveSelectionType == Point; + return myToAllowOverlap || GetActiveSelectionType() == SelectMgr_SelectionType_Point; } //======================================================================= @@ -412,11 +505,17 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const //======================================================================= const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const { - if (myActiveSelectionType == Polyline) + if (myActiveSelectingVolume.IsNull()) + { return NULL; - - const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get()); - return aFr->GetVertices(); + } + const SelectMgr_RectangularFrustum* aRectFrustum = + static_cast<const SelectMgr_RectangularFrustum*> (myActiveSelectingVolume.get()); + if (aRectFrustum == NULL) + { + return NULL; + } + return aRectFrustum->GetVertices(); } //======================================================================= @@ -425,11 +524,11 @@ const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const //======================================================================= gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPickedPnt() const { - if (myActiveSelectionType == Polyline) + if (myActiveSelectingVolume.IsNull()) + { return gp_Pnt(); - - const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get()); - return aFr->GetNearPnt(); + } + return myActiveSelectingVolume->GetNearPnt(); } //======================================================================= @@ -438,11 +537,64 @@ gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPickedPnt() const //======================================================================= gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPickedPnt() const { - if (myActiveSelectionType == Polyline) - return gp_Pnt(); + if (myActiveSelectingVolume.IsNull()) + { + return gp_Pnt(RealLast(), RealLast(), RealLast()); + } + return myActiveSelectingVolume->GetFarPnt(); +} - const SelectMgr_RectangularFrustum* aFr = static_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get()); - return aFr->GetFarPnt(); +//======================================================================= +// function : GetViewRayDirection +// purpose : +//======================================================================= +gp_Dir SelectMgr_SelectingVolumeManager::GetViewRayDirection() const +{ + if (myActiveSelectingVolume.IsNull()) + { + return gp_Dir(); + } + return myActiveSelectingVolume->GetViewRayDirection(); +} + +//======================================================================= +// function : IsScalableActiveVolume +// purpose : +//======================================================================= +Standard_Boolean SelectMgr_SelectingVolumeManager::IsScalableActiveVolume() const +{ + if (myActiveSelectingVolume.IsNull()) + { + return Standard_False; + } + return myActiveSelectingVolume->IsScalable(); +} + +//======================================================================= +// function : GetMousePosition +// purpose : +//======================================================================= +gp_Pnt2d SelectMgr_SelectingVolumeManager::GetMousePosition() const +{ + if (myActiveSelectingVolume.IsNull()) + { + return gp_Pnt2d(RealLast(), RealLast()); + } + return myActiveSelectingVolume->GetMousePosition(); +} + +//======================================================================= +// function : GetPlanes +// purpose : +//======================================================================= +void SelectMgr_SelectingVolumeManager::GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const +{ + if (myActiveSelectingVolume.IsNull()) + { + thePlaneEquations.Clear(); + return; + } + return myActiveSelectingVolume->GetPlanes (thePlaneEquations); } //======================================================================= @@ -455,21 +607,26 @@ void SelectMgr_SelectingVolumeManager::SetViewClipping (const Handle(Graphic3d_S { myViewClipPlanes = theViewPlanes; myObjectClipPlanes = theObjPlanes; - if (myActiveSelectionType != Point) + if (GetActiveSelectionType() != SelectMgr_SelectionType_Point) + { return; + } const SelectMgr_SelectingVolumeManager* aWorldSelMgr = theWorldSelMgr != NULL ? theWorldSelMgr : this; - const SelectMgr_RectangularFrustum* aFrustum = static_cast<const SelectMgr_RectangularFrustum*>(aWorldSelMgr->mySelectingVolumes[Frustum].get()); myViewClipRange.SetVoid(); if (!theViewPlanes.IsNull() && !theViewPlanes->IsEmpty()) { - myViewClipRange.AddClippingPlanes (*theViewPlanes, gp_Ax1 (aFrustum->GetNearPnt(), aFrustum->GetViewRayDirection())); + myViewClipRange.AddClippingPlanes (*theViewPlanes, + gp_Ax1(aWorldSelMgr->myActiveSelectingVolume->GetNearPnt(), + aWorldSelMgr->myActiveSelectingVolume->GetViewRayDirection())); } if (!theObjPlanes.IsNull() && !theObjPlanes->IsEmpty()) { - myViewClipRange.AddClippingPlanes (*theObjPlanes, gp_Ax1 (aFrustum->GetNearPnt(), aFrustum->GetViewRayDirection())); + myViewClipRange.AddClippingPlanes (*theObjPlanes, + gp_Ax1(aWorldSelMgr->myActiveSelectingVolume->GetNearPnt(), + aWorldSelMgr->myActiveSelectingVolume->GetViewRayDirection())); } } @@ -492,12 +649,7 @@ void SelectMgr_SelectingVolumeManager::DumpJson (Standard_OStream& theOStream, S { OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_SelectingVolumeManager) - for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) - { - const Handle(SelectMgr_BaseFrustum)& aSelectingVolume = mySelectingVolumes[anIdx]; - OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aSelectingVolume.get()) - } - + OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myActiveSelectingVolume.get()) OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myViewClipPlanes.get()) OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myObjectClipPlanes.get()) diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 12b492761f..76f2d04e34 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -16,28 +16,54 @@ #ifndef _SelectMgr_SelectingVolumeManager_HeaderFile #define _SelectMgr_SelectingVolumeManager_HeaderFile -#include <NCollection_Handle.hxx> - -#include <Graphic3d_Camera.hxx> -#include <Graphic3d_SequenceOfHClipPlane.hxx> -#include <Graphic3d_WorldViewProjState.hxx> - -#include <SelectMgr_BaseFrustum.hxx> -#include <SelectMgr_RectangularFrustum.hxx> -#include <SelectMgr_TriangularFrustumSet.hxx> #include <SelectBasics_SelectingVolumeManager.hxx> +#include <SelectMgr_BaseIntersector.hxx> +#include <SelectMgr_VectorTypes.hxx> +#include <SelectMgr_ViewClipRange.hxx> + //! This class is used to switch between active selecting volumes depending -//! on selection type chosen by the user +//! on selection type chosen by the user. +//! The sample of correct selection volume initialization procedure: +//! @code +//! aMgr.InitPointSelectingVolume (aMousePos); +//! aMgr.SetPixelTolerance (aTolerance); +//! aMgr.SetCamera (aCamera); +//! aMgr.SetWindowSize (aWidth, aHeight); +//! aMgr.BuildSelectingVolume(); +//! @endcode class SelectMgr_SelectingVolumeManager : public SelectBasics_SelectingVolumeManager { public: //! Creates instances of all available selecting volume types - Standard_EXPORT SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums = Standard_True); + Standard_EXPORT SelectMgr_SelectingVolumeManager(); virtual ~SelectMgr_SelectingVolumeManager() {} + //! Creates, initializes and activates rectangular selecting frustum for point selection + Standard_EXPORT void InitPointSelectingVolume (const gp_Pnt2d& thePoint); + + //! Creates, initializes and activates rectangular selecting frustum for box selection + Standard_EXPORT void InitBoxSelectingVolume (const gp_Pnt2d& theMinPt, + const gp_Pnt2d& theMaxPt); + + //! Creates, initializes and activates set of triangular selecting frustums for polyline selection + Standard_EXPORT void InitPolylineSelectingVolume (const TColgp_Array1OfPnt2d& thePoints); + + //! Sets as active the custom selecting volume + Standard_EXPORT void InitSelectingVolume (const Handle(SelectMgr_BaseIntersector)& theVolume); + + //! Builds previously initialized selecting volume. + Standard_EXPORT void BuildSelectingVolume(); + + //! Returns active selecting volume that was built during last + //! run of OCCT selection mechanism + const Handle(SelectMgr_BaseIntersector)& ActiveVolume() const { return myActiveSelectingVolume; } + + // Returns active selection type (point, box, polyline) + Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE; + //! IMPORTANT: Scaling makes sense only for frustum built on a single point! //! Note that this method does not perform any checks on type of the frustum. //! @@ -50,19 +76,21 @@ public: //! frustum from scratch. Can be null if reconstruction is not expected furthermore. Standard_EXPORT virtual SelectMgr_SelectingVolumeManager ScaleAndTransform (const Standard_Integer theScaleFactor, const gp_GTrsf& theTrsf, - const Handle(SelectMgr_FrustumBuilder)& theBuilder = NULL) const; + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const; - Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE; - - Standard_EXPORT void SetActiveSelectionType (const SelectionType& theType); +public: //! Returns current camera definition. - const Handle(Graphic3d_Camera)& Camera() const { return mySelectingVolumes[Frustum]->Camera(); } + Standard_EXPORT const Handle(Graphic3d_Camera)& Camera() const; //! Updates camera projection and orientation matrices in all selecting volumes + //! Note: this method should be called after selection volume building + //! else exception will be thrown Standard_EXPORT void SetCamera (const Handle(Graphic3d_Camera) theCamera); //! Updates camera projection and orientation matrices in all selecting volumes + //! Note: this method should be called after selection volume building + //! else exception will be thrown Standard_EXPORT void SetCamera (const Graphic3d_Mat4d& theProjection, const Graphic3d_Mat4d& theWorldView, const Standard_Boolean theIsOrthographic, @@ -80,29 +108,24 @@ public: Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const; //! Updates viewport in all selecting volumes + //! Note: this method should be called after selection volume building + //! else exception will be thrown Standard_EXPORT void SetViewport (const Standard_Real theX, const Standard_Real theY, const Standard_Real theWidth, const Standard_Real theHeight); //! Updates pixel tolerance in all selecting volumes + //! Note: this method should be called after selection volume building + //! else exception will be thrown Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTolerance); //! Updates window size in all selecting volumes + //! Note: this method should be called after selection volume building + //! else exception will be thrown Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight); - //! Builds rectangular selecting frustum for point selection - Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& thePoint); - - //! Builds rectangular selecting frustum for box selection - Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& theMinPt, - const gp_Pnt2d& theMaxPt); - - //! Builds set of triangular selecting frustums for polyline selection - Standard_EXPORT void BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints); - - //! SAT intersection test between defined volume and given axis-aligned box Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, const SelectMgr_Vec3& theBoxMax, @@ -203,47 +226,50 @@ public: //! correspondingly) onto far view frustum plane Standard_EXPORT virtual gp_Pnt GetFarPickedPnt() const Standard_OVERRIDE; - //! Return mouse coordinates for Point selection mode. - virtual gp_Pnt2d GetMousePosition() const Standard_OVERRIDE - { - if (myActiveSelectionType != Point) - { - return gp_Pnt2d (RealLast(), RealLast()); - } - const SelectMgr_RectangularFrustum* aFr = reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get()); - return aFr->GetMousePosition(); - } + //! Valid only for point and rectangular selection. + //! Returns view ray direction + Standard_EXPORT virtual gp_Dir GetViewRayDirection() const Standard_OVERRIDE; - //! Returns active selecting volume that was built during last - //! run of OCCT selection mechanism - Handle(SelectMgr_BaseFrustum) ActiveVolume() const - { - if (myActiveSelectionType == Unknown) - return Handle(SelectMgr_BaseFrustum)(); + //! Checks if it is possible to scale current active selecting volume + Standard_EXPORT virtual Standard_Boolean IsScalableActiveVolume() const Standard_OVERRIDE; - return mySelectingVolumes[myActiveSelectionType / 2]; - } + //! Returns mouse coordinates for Point selection mode. + //! @return infinite point in case of unsupport of mouse position for this active selection volume. + Standard_EXPORT virtual gp_Pnt2d GetMousePosition() const Standard_OVERRIDE; //! Stores plane equation coefficients (in the following form: //! Ax + By + Cz + D = 0) to the given vector - virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE - { - if (myActiveSelectionType == Unknown) - { - thePlaneEquations.Clear(); - return; - } - - return mySelectingVolumes[myActiveSelectionType / 2]->GetPlanes (thePlaneEquations); - } + Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE; //! Dumps the content of me into the stream - Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; + +public: + + Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead") + static const SelectMgr_SelectionType Point = SelectMgr_SelectionType_Point; + + Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead") + static const SelectMgr_SelectionType Box = SelectMgr_SelectionType_Point; + + Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead") + static const SelectMgr_SelectionType Polyline = SelectMgr_SelectionType_Point; + + Standard_DEPRECATED("Deprecated alias - SelectMgr_SelectionType should be used instead") + static const SelectMgr_SelectionType Unknown = SelectMgr_SelectionType_Point; + + Standard_DEPRECATED("Deprecated method - InitPointSelectingVolume() and Build() methods should be used instead") + Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& thePoint); + + Standard_DEPRECATED("Deprecated method - InitBoxSelectingVolume() and Build() should be used instead") + Standard_EXPORT void BuildSelectingVolume (const gp_Pnt2d& theMinPt, + const gp_Pnt2d& theMaxPt); + + Standard_DEPRECATED("Deprecated method - InitPolylineSelectingVolume() and Build() should be used instead") + Standard_EXPORT void BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints); private: - enum { Frustum, FrustumSet, VolumeTypesNb }; //!< Defines the amount of available selecting volumes - - Handle(SelectMgr_BaseFrustum) mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes + Handle(SelectMgr_BaseIntersector) myActiveSelectingVolume; Handle(Graphic3d_SequenceOfHClipPlane) myViewClipPlanes; //!< view clipping planes Handle(Graphic3d_SequenceOfHClipPlane) myObjectClipPlanes; //!< object clipping planes SelectMgr_ViewClipRange myViewClipRange; diff --git a/src/SelectMgr/SelectMgr_SelectionType.hxx b/src/SelectMgr/SelectMgr_SelectionType.hxx new file mode 100644 index 0000000000..00e6e43cd2 --- /dev/null +++ b/src/SelectMgr/SelectMgr_SelectionType.hxx @@ -0,0 +1,26 @@ +// Copyright (c) 2021 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _SelectMgr_SelectionType_HeaderFile +#define _SelectMgr_SelectionType_HeaderFile + +//! Possible selection types +enum SelectMgr_SelectionType +{ + SelectMgr_SelectionType_Unknown = -1, //!< undefined selection type + SelectMgr_SelectionType_Point, //!< selection by point (frustum with some tolerance or axis) + SelectMgr_SelectionType_Box, //!< rectangle selection + SelectMgr_SelectionType_Polyline //!< polygonal selection +}; + +#endif // _SelectMgr_SelectionType_HeaderFile diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx index e7b9aa37c4..8395cb8a7a 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx @@ -15,6 +15,8 @@ #include <SelectMgr_TriangularFrustum.hxx> +#include <SelectMgr_FrustumBuilder.hxx> + IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,Standard_Transient) SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum() @@ -77,27 +79,36 @@ void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFr } //======================================================================= -// function : SelectMgr_TriangularFrustum -// purpose : Creates new triangular frustum with bases of triangles with -// vertices theP1, theP2 and theP3 projections onto near and -// far view frustum planes +// function : Init +// purpose : //======================================================================= -void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1, - const gp_Pnt2d& theP2, - const gp_Pnt2d& theP3) +void SelectMgr_TriangularFrustum::Init (const gp_Pnt2d& theP1, + const gp_Pnt2d& theP2, + const gp_Pnt2d& theP3) +{ + mySelTriangle.Points[0] = theP1; + mySelTriangle.Points[1] = theP2; + mySelTriangle.Points[2] = theP3; +} + +//======================================================================= +// function : Build +// purpose : +//======================================================================= +void SelectMgr_TriangularFrustum::Build() { // V0_Near - myVertices[0] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 0.0); + myVertices[0] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[0].X(), mySelTriangle.Points[0].Y(), 0.0); // V1_Near - myVertices[1] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 0.0); + myVertices[1] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[1].X(), mySelTriangle.Points[1].Y(), 0.0); // V2_Near - myVertices[2] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 0.0); + myVertices[2] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[2].X(), mySelTriangle.Points[2].Y(), 0.0); // V0_Far - myVertices[3] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 1.0); + myVertices[3] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[0].X(), mySelTriangle.Points[0].Y(), 1.0); // V1_Far - myVertices[4] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 1.0); + myVertices[4] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[1].X(), mySelTriangle.Points[1].Y(), 1.0); // V2_Far - myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0); + myVertices[5] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[2].X(), mySelTriangle.Points[2].Y(), 1.0); // V0_Near - V0_Far myEdgeDirs[0] = myVertices[0].XYZ() - myVertices[3].XYZ(); @@ -128,8 +139,9 @@ void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1, // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. //======================================================================= -Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/, - const gp_GTrsf& theTrsf) const +Handle(SelectMgr_BaseIntersector) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)&) const { Handle(SelectMgr_TriangularFrustum) aRes = new SelectMgr_TriangularFrustum(); @@ -159,6 +171,8 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustum::ScaleAndTransform (co cacheVertexProjections (aRes.get()); + aRes->mySelTriangle = mySelTriangle; + return aRes; } diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx index 2a37887542..aacf530652 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx @@ -23,25 +23,39 @@ //! frustum and sensitive entities. //! Overlap detection tests are implemented according to the terms of separating axis //! theorem (SAT). +//! NOTE: the object of this class can be created only as part of SelectMgr_TriangularFrustumSet. class SelectMgr_TriangularFrustum : public SelectMgr_Frustum<3> { -public: +protected: //! Creates new triangular frustum with bases of triangles with vertices theP1, //! theP2 and theP3 projections onto near and far view frustum planes - SelectMgr_TriangularFrustum() {}; + SelectMgr_TriangularFrustum() {} + +public: + + //! Auxiliary structure to define selection triangle + struct SelectionTriangle + { + gp_Pnt2d Points[3]; + }; Standard_EXPORT ~SelectMgr_TriangularFrustum(); + //! Initializes selection triangle by input points + Standard_EXPORT void Init (const gp_Pnt2d& theP1, + const gp_Pnt2d& theP2, + const gp_Pnt2d& theP3); + //! Creates new triangular frustum with bases of triangles with vertices theP1, theP2 and theP3 //! projections onto near and far view frustum planes (only for triangular frustums) - Standard_EXPORT virtual void Build (const gp_Pnt2d& theP1, - const gp_Pnt2d& theP2, - const gp_Pnt2d& theP3) Standard_OVERRIDE; + //! NOTE: it should be called after Init() method + Standard_EXPORT virtual void Build() Standard_OVERRIDE; //! Returns a copy of the frustum transformed according to the matrix given - Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScale, - const gp_GTrsf& theTrsf) const Standard_OVERRIDE; + Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScale, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const Standard_OVERRIDE; // SAT Tests for different objects @@ -100,7 +114,15 @@ private: void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const; - DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,SelectMgr_Frustum<3>) +protected: + + SelectionTriangle mySelTriangle; //!< parameters of selection triangle (it is used to build triangle frustum) + +public: + + DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum, SelectMgr_Frustum<3>) + + friend class SelectMgr_TriangularFrustumSet; }; #endif // _SelectMgr_TriangularFrustum_HeaderFile diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx index c7f50bf5bd..977201a7ad 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx @@ -16,9 +16,9 @@ #include <BRepMesh_DataStructureOfDelaun.hxx> #include <BRepMesh_Delaun.hxx> #include <NCollection_IncAllocator.hxx> +#include <SelectMgr_FrustumBuilder.hxx> #include <SelectMgr_TriangularFrustumSet.hxx> -#include <SelectMgr_TriangularFrustum.hxx> #define MEMORY_BLOCK_SIZE 512 * 7 @@ -28,42 +28,61 @@ // ======================================================================= SelectMgr_TriangularFrustumSet::SelectMgr_TriangularFrustumSet() : myToAllowOverlap (Standard_False) -{} +{ +} // ======================================================================= -// function : BuildSelectingVolume +// function : Init +// purpose : +// ======================================================================= +void SelectMgr_TriangularFrustumSet::Init (const TColgp_Array1OfPnt2d& thePoints) +{ + if (mySelPolyline.Points.IsNull()) + { + mySelPolyline.Points = new TColgp_HArray1OfPnt2d (thePoints.Lower(), thePoints.Upper()); + } + mySelPolyline.Points->Resize (thePoints.Lower(), thePoints.Upper(), false); + *mySelPolyline.Points = thePoints; + mySelectionType = SelectMgr_SelectionType_Polyline; +} + +// ======================================================================= +// function : Build // purpose : Meshes polygon bounded by polyline. Than organizes a set of // triangular frustums, where each triangle's projection onto // near and far view frustum planes is considered as a frustum // base // ======================================================================= -void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoints) +void SelectMgr_TriangularFrustumSet::Build() { + Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline || !mySelPolyline.Points.IsNull(), + "Error! SelectMgr_TriangularFrustumSet::Build() should be called after selection frustum initialization"); + myFrustums.Clear(); Handle(NCollection_IncAllocator) anAllocator = new NCollection_IncAllocator (MEMORY_BLOCK_SIZE); Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun (anAllocator); - Standard_Integer aPtsLower = thePoints.Lower(); - Standard_Integer aPtsUpper = thePoints.Upper(); - IMeshData::VectorOfInteger anIndexes (thePoints.Size(), anAllocator); - myBoundaryPoints.Resize (aPtsLower, aPtsLower + 2 * (thePoints.Size()) - 1, Standard_False); + Standard_Integer aPtsLower = mySelPolyline.Points->Lower(); + Standard_Integer aPtsUpper = mySelPolyline.Points->Upper(); + IMeshData::VectorOfInteger anIndexes (mySelPolyline.Points->Size(), anAllocator); + myBoundaryPoints.Resize (aPtsLower, aPtsLower + 2 * (mySelPolyline.Points->Size()) - 1, Standard_False); for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx) { - BRepMesh_Vertex aVertex (thePoints.Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier); + BRepMesh_Vertex aVertex (mySelPolyline.Points->Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier); anIndexes.Append (aMeshStructure->AddNode (aVertex)); const gp_Pnt aNearPnt = myBuilder->ProjectPntOnViewPlane (aVertex.Coord().X(), aVertex.Coord().Y(), 0.0); const gp_Pnt aFarPnt = myBuilder->ProjectPntOnViewPlane (aVertex.Coord().X(), aVertex.Coord().Y(), 1.0); myBoundaryPoints.SetValue (aPtIdx, aNearPnt); - myBoundaryPoints.SetValue (aPtIdx + thePoints.Size(), aFarPnt); + myBoundaryPoints.SetValue (aPtIdx + mySelPolyline.Points->Size(), aFarPnt); } Standard_Real aPtSum = 0; for (Standard_Integer aIdx = aPtsLower; aIdx <= aPtsUpper; ++aIdx) { - Standard_Integer aNextIdx = (aIdx % thePoints.Length()) + 1; - aPtSum += (thePoints.Value (aNextIdx).Coord().X() - thePoints.Value (aIdx).Coord().X()) - * (thePoints.Value (aNextIdx).Coord().Y() + thePoints.Value (aIdx).Coord().Y()); + Standard_Integer aNextIdx = (aIdx % mySelPolyline.Points->Length()) + 1; + aPtSum += (mySelPolyline.Points->Value (aNextIdx).Coord().X() - mySelPolyline.Points->Value (aIdx).Coord().X()) + * (mySelPolyline.Points->Value (aNextIdx).Coord().Y() + mySelPolyline.Points->Value (aIdx).Coord().Y()); } Standard_Boolean isClockwiseOrdered = aPtSum < 0; @@ -102,8 +121,9 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint } Handle(SelectMgr_TriangularFrustum) aTrFrustum = new SelectMgr_TriangularFrustum(); + aTrFrustum->Init (aPts[0], aPts[1], aPts[2]); aTrFrustum->SetBuilder (myBuilder); - aTrFrustum->Build (aPts[0], aPts[1], aPts[2]); + aTrFrustum->Build(); myFrustums.Append (aTrFrustum); } @@ -122,14 +142,18 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. // ======================================================================= -Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale, - const gp_GTrsf& theTrsf) const +Handle(SelectMgr_BaseIntersector) SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const { + Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::ScaleAndTransform() should be called after selection frustum initialization"); + Handle(SelectMgr_TriangularFrustumSet) aRes = new SelectMgr_TriangularFrustumSet(); for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { - aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf))); + aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf, theBuilder))); } aRes->myBoundaryPoints.Resize (myBoundaryPoints.Lower(), myBoundaryPoints.Upper(), Standard_False); @@ -140,6 +164,9 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustumSet::ScaleAndTransform aRes->myBoundaryPoints.SetValue (anIdx, aPoint); } + aRes->mySelectionType = mySelectionType; + aRes->mySelPolyline.Points = mySelPolyline.Points; + aRes->SetBuilder (theBuilder); return aRes; } @@ -152,6 +179,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization"); + for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, theClipRange, thePickResult)) @@ -169,6 +199,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& const SelectMgr_Vec3& theMaxPnt, Standard_Boolean* theInside) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization"); + for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, NULL)) @@ -217,6 +250,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt, const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization"); + for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { if (anIter.Value()->Overlaps (thePnt, theClipRange, thePickResult)) @@ -235,6 +271,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const TColgp_Array1Of const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization"); + for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { if (anIter.Value()->Overlaps (theArrayOfPts, theSensType, theClipRange, thePickResult)) @@ -271,6 +310,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt1 const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization"); + for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { if (anIter.Value()->Overlaps (thePnt1, thePnt2, theClipRange, thePickResult)) @@ -304,6 +346,9 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt1 const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const { + Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Polyline, + "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization"); + for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { if (anIter.Value()->Overlaps (thePnt1, thePnt2, thePnt3, theSensType, theClipRange, thePickResult)) @@ -421,6 +466,16 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::segmentTriangleIntersection (co return Standard_True; } +// ======================================================================= +// function : DetectedPoint +// purpose : +// ======================================================================= +gp_Pnt SelectMgr_TriangularFrustumSet::DetectedPoint (const Standard_Real theDepth) const +{ + (void )theDepth; + throw Standard_ProgramError ("SelectMgr_TriangularFrustumSet::DetectedPoint() should not be called for Polyline selection type"); +} + //======================================================================= //function : DumpJson //purpose : diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx index 372dcce208..8c53e407b8 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx @@ -16,11 +16,8 @@ #ifndef _SelectMgr_TriangularFrustumSet_HeaderFile #define _SelectMgr_TriangularFrustumSet_HeaderFile -#include <NCollection_Handle.hxx> -#include <NCollection_List.hxx> - -#include <SelectMgr_BaseFrustum.hxx> #include <SelectMgr_TriangularFrustum.hxx> +#include <TColgp_HArray1OfPnt2d.hxx> typedef NCollection_List<Handle(SelectMgr_TriangularFrustum)> SelectMgr_TriangFrustums; typedef NCollection_List<Handle(SelectMgr_TriangularFrustum)>::Iterator SelectMgr_TriangFrustumsIter; @@ -37,18 +34,29 @@ class SelectMgr_TriangularFrustumSet : public SelectMgr_BaseFrustum { public: + //! Auxiliary structure to define selection polyline + struct SelectionPolyline + { + Handle(TColgp_HArray1OfPnt2d) Points; + }; + SelectMgr_TriangularFrustumSet(); ~SelectMgr_TriangularFrustumSet() {}; + //! Initializes set of triangular frustums by polyline + Standard_EXPORT void Init (const TColgp_Array1OfPnt2d& thePoints); + //! Meshes polygon bounded by polyline. Than organizes a set of triangular frustums, //! where each triangle's projection onto near and far view frustum planes is //! considered as a frustum base - Standard_EXPORT virtual void Build (const TColgp_Array1OfPnt2d& thePoints) Standard_OVERRIDE; + //! NOTE: it should be called after Init() method + Standard_EXPORT virtual void Build() Standard_OVERRIDE; //! Returns a copy of the frustum with all sub-volumes transformed according to the matrix given - Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScale, - const gp_GTrsf& theTrsf) const Standard_OVERRIDE; + Standard_EXPORT virtual Handle(SelectMgr_BaseIntersector) ScaleAndTransform (const Standard_Integer theScale, + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const Standard_OVERRIDE; Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt, const SelectMgr_Vec3& theMaxPnt, @@ -80,6 +88,9 @@ public: const SelectMgr_ViewClipRange& theClipRange, SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE; + //! Calculates the point on a view ray that was detected during the run of selection algo by given depth + Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE; + //! Stores plane equation coefficients (in the following form: //! Ax + By + Cz + D = 0) to the given vector Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE; @@ -102,9 +113,10 @@ private: private: - SelectMgr_TriangFrustums myFrustums; - TColgp_Array1OfPnt myBoundaryPoints; - Standard_Boolean myToAllowOverlap; + SelectMgr_TriangFrustums myFrustums; //!< set of triangular frustums + SelectionPolyline mySelPolyline; //!< parameters of selection polyline (it is used to build triangle frustum set) + TColgp_Array1OfPnt myBoundaryPoints; //!< boundary points + Standard_Boolean myToAllowOverlap; //!< flag to detect only fully included sensitives or not }; #endif // _SelectMgr_TriangularFrustumSet_HeaderFile diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 30805b3e38..a84e6c9243 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -24,6 +24,7 @@ #include <Select3D_SensitiveEntity.hxx> #include <SelectBasics_PickResult.hxx> #include <SelectMgr_EntityOwner.hxx> +#include <SelectMgr_FrustumBuilder.hxx> #include <SelectMgr_SortCriterion.hxx> #include <SelectMgr_SensitiveEntitySet.hxx> #include <TColStd_Array1OfInteger.hxx> @@ -79,7 +80,7 @@ void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriter const gp_GTrsf& theInversedTrsf, const SelectMgr_SelectingVolumeManager& theMgr) const { - if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { return; } @@ -247,7 +248,7 @@ void SelectMgr_ViewerSelector::Clear() //======================================================================= Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity) { - return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point + return mySelectingVolumeMgr.IsScalableActiveVolume() && sensitivity (theEntity) < myTolerances.Tolerance(); } @@ -292,7 +293,7 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEnti { ++aPrevCriterion->NbOwnerMatches; aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches; - if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box) + if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box) { if (aCriterion.IsCloserDepth (*aPrevCriterion)) { @@ -379,6 +380,10 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable } else { + if (theCamera.IsNull()) + { + return; + } gp_GTrsf aTPers; Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight); @@ -446,7 +451,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable } if (!theMgr.ViewClipping().IsNull() && - theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box) + theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box) { Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0)); // If box selection is active, and the whole sensitive tree is out of the clip planes @@ -475,7 +480,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable Standard_Integer aHead = -1; Standard_Integer aNode = 0; // a root node SelectMgr_FrustumCache aScaledTrnsfFrustums; - SelectMgr_SelectingVolumeManager aTmpMgr (false); + SelectMgr_SelectingVolumeManager aTmpMgr; for (;;) { if (!aSensitivesTree->IsOuter (aNode)) @@ -513,7 +518,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable { bool aClipped = false; if (!theMgr.ViewClipping().IsNull() && - theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box) + theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box) { Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode)); // If box selection is active, and the whole sensitive tree is out of the clip planes @@ -569,8 +574,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable // in case of Box/Polyline selection - keep only Owners having all Entities detected if (mySelectingVolumeMgr.IsOverlapAllowed() - || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box - && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline)) + || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box + && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline)) { return; } @@ -599,8 +604,8 @@ void SelectMgr_ViewerSelector::TraverseSensitives() mystored.Clear(); - Standard_Integer aWidth; - Standard_Integer aHeight; + Standard_Integer aWidth = 0; + Standard_Integer aHeight = 0; mySelectingVolumeMgr.WindowSize (aWidth, aHeight); mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(), mySelectingVolumeMgr.ProjectionMatrix(), @@ -631,13 +636,17 @@ void SelectMgr_ViewerSelector::TraverseSensitives() gp_GTrsf aTFrustum; - SelectMgr_SelectingVolumeManager aMgr (Standard_False); + SelectMgr_SelectingVolumeManager aMgr; // for 2D space selection transform selecting volumes to perform overap testing // directly in camera's eye space omitting the camera position, which is not // needed there at all if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent) { + if (aCamera.IsNull()) + { + continue; + } const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix(); aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0)); aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1)); @@ -653,7 +662,7 @@ void SelectMgr_ViewerSelector::TraverseSensitives() // define corresponding frustum builder parameters Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder(); aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix(), - !aCamera.IsNull() && aCamera->IsZeroToOneDepth()); + aCamera->IsZeroToOneDepth()); aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT); aBuilder->SetWindowSize (aWidth, aHeight); aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder); diff --git a/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx b/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx index cbd687c00e..94bf57236e 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector3d.cxx @@ -49,20 +49,22 @@ void SelectMgr_ViewerSelector3d::Pick (const Standard_Integer theXPix, const Handle(V3d_View)& theView) { updateZLayers (theView); + + gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix), + static_cast<Standard_Real> (theYPix)); + mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos); + if(myToUpdateTolerance) { mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance()); myToUpdateTolerance = Standard_False; } - mySelectingVolumeMgr.SetCamera (theView->Camera()); - mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Point); Standard_Integer aWidth = 0, aHeight = 0; theView->Window()->Size (aWidth, aHeight); mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight); - gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix), - static_cast<Standard_Real> (theYPix)); - mySelectingVolumeMgr.BuildSelectingVolume (aMousePos); + + mySelectingVolumeMgr.BuildSelectingVolume(); mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL); TraverseSensitives(); @@ -79,20 +81,21 @@ void SelectMgr_ViewerSelector3d::Pick (const Standard_Integer theXPMin, const Handle(V3d_View)& theView) { updateZLayers (theView); - mySelectingVolumeMgr.SetCamera (theView->Camera()); - mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Box); - Standard_Integer aWidth = 0, aHeight = 0; - theView->Window()->Size (aWidth, aHeight); - mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight); + gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXPMin), static_cast<Standard_Real> (theYPMin)); gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXPMax), static_cast<Standard_Real> (theYPMax)); - mySelectingVolumeMgr.BuildSelectingVolume (aMinMousePos, - aMaxMousePos); + mySelectingVolumeMgr.InitBoxSelectingVolume (aMinMousePos, + aMaxMousePos); + mySelectingVolumeMgr.SetCamera (theView->Camera()); + Standard_Integer aWidth = 0, aHeight = 0; + theView->Window()->Size (aWidth, aHeight); + mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight); + + mySelectingVolumeMgr.BuildSelectingVolume(); mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL); - TraverseSensitives(); } @@ -104,13 +107,13 @@ void SelectMgr_ViewerSelector3d::Pick (const TColgp_Array1OfPnt2d& thePolyline, const Handle(V3d_View)& theView) { updateZLayers (theView); + + mySelectingVolumeMgr.InitPolylineSelectingVolume (thePolyline); mySelectingVolumeMgr.SetCamera (theView->Camera()); - mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Polyline); Standard_Integer aWidth = 0, aHeight = 0; theView->Window()->Size (aWidth, aHeight); mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight); - mySelectingVolumeMgr.BuildSelectingVolume (thePolyline); - + mySelectingVolumeMgr.BuildSelectingVolume(); mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL); TraverseSensitives();