diff --git a/src/AIS/AIS_InteractiveContext.cdl b/src/AIS/AIS_InteractiveContext.cdl index 8026b714fc..b149dfd173 100644 --- a/src/AIS/AIS_InteractiveContext.cdl +++ b/src/AIS/AIS_InteractiveContext.cdl @@ -428,8 +428,8 @@ is -- Removes selection mode from Interactive Objects. -- aMode provides the selection mode index of the entity aniobj. - SetPixelTolerance(me:mutable; - aPrecision: Real from Standard = 2.0); + SetPixelTolerance (me:mutable; + aPrecision: Integer from Standard = 2); ---Level: Public ---Purpose: Disables the mechanism of adaptive tolerance calculation in SelectMgr_ViewerSelector and -- sets the given tolerance for ALL sensitive entities activated. For more information, see @@ -437,7 +437,7 @@ is -- Warning: When a local context is open the sensitivity is apply on it -- instead on the main context. - PixelTolerance(me) returns Real from Standard; + PixelTolerance(me) returns Integer from Standard; ---Level: Public ---Purpose: Returns the pixel tolerance. diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx index e653481028..da36d0752a 100644 --- a/src/AIS/AIS_InteractiveContext.cxx +++ b/src/AIS/AIS_InteractiveContext.cxx @@ -2596,7 +2596,7 @@ void AIS_InteractiveContext::UnsetSelectionMode (const Handle(AIS_InteractiveObj // sensitive entities activated. For more information, see // SelectMgr_ViewerSelector.hxx //======================================================================= -void AIS_InteractiveContext::SetPixelTolerance (const Standard_Real thePrecision) +void AIS_InteractiveContext::SetPixelTolerance (const Standard_Integer thePrecision) { if (HasOpenedContext()) { @@ -2612,7 +2612,7 @@ void AIS_InteractiveContext::SetPixelTolerance (const Standard_Real thePrecision //function : PixelTolerance //purpose : //======================================================================= -Standard_Real AIS_InteractiveContext::PixelTolerance() const +Standard_Integer AIS_InteractiveContext::PixelTolerance() const { return HasOpenedContext() ? myLocalContexts (myCurLocalIndex)->PixelTolerance() @@ -2677,7 +2677,7 @@ void AIS_InteractiveContext::InitAttributes() aLineAspect->SetTypeOfLine (Aspect_TOL_DASH); // tolerance to 2 pixels... - SetPixelTolerance (2.0); + SetPixelTolerance (2); // Customizing the drawer for trihedrons and planes... Handle(Prs3d_DatumAspect) aTrihAspect = myDefaultDrawer->DatumAspect(); diff --git a/src/AIS/AIS_LocalContext.cdl b/src/AIS/AIS_LocalContext.cdl index 5a9b10424f..f123a8693c 100644 --- a/src/AIS/AIS_LocalContext.cdl +++ b/src/AIS/AIS_LocalContext.cdl @@ -437,13 +437,13 @@ is HiCol : out NameOfColor from Quantity) returns Boolean from Standard; - SetPixelTolerance(me:mutable; - aPrecision: Real from Standard = 2); + SetPixelTolerance (me:mutable; + aPrecision: Integer from Standard = 2); ---Level: Public ---Purpose: Define the current selection sensitivity for -- this local context according to the view size. - PixelTolerance(me) returns Real from Standard; + PixelTolerance(me) returns Integer from Standard; ---Level: Public ---Purpose: Returns the pixel tolerance. diff --git a/src/AIS/AIS_LocalContext.cxx b/src/AIS/AIS_LocalContext.cxx index 259cf016f6..389a9f4d0e 100644 --- a/src/AIS/AIS_LocalContext.cxx +++ b/src/AIS/AIS_LocalContext.cxx @@ -1139,12 +1139,12 @@ Standard_Boolean AIS_LocalContext::IsImmediateModeOn() const return myMainPM->IsImmediateModeOn(); } -void AIS_LocalContext::SetPixelTolerance(const Standard_Real aPrecision) { +void AIS_LocalContext::SetPixelTolerance(const Standard_Integer aPrecision) { myMainVS->SetPixelTolerance(aPrecision); } -Standard_Real AIS_LocalContext::PixelTolerance() const { +Standard_Integer AIS_LocalContext::PixelTolerance() const { return myMainVS->PixelTolerance(); } diff --git a/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx b/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx index 1a17c1b4b6..c276f47e9e 100644 --- a/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx +++ b/src/IVtkOCC/IVtkOCC_ViewerSelector.cxx @@ -187,7 +187,6 @@ void IVtkOCC_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSel theSelection->SetSelectionState (SelectMgr_SOS_Activated); myTolerances.Add (theSelection->Sensitivity()); - mytolerance = myTolerances.Tolerance(); myToUpdateTolerance = Standard_True; } @@ -205,6 +204,5 @@ void IVtkOCC_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theS theSelection->SetSelectionState (SelectMgr_SOS_Deactivated); myTolerances.Decrement (theSelection->Sensitivity()); - mytolerance = myTolerances.Tolerance(); myToUpdateTolerance = Standard_True; } diff --git a/src/MeshVS/MeshVS_DummySensitiveEntity.cxx b/src/MeshVS/MeshVS_DummySensitiveEntity.cxx index 16c53eae64..bfe2204f6d 100644 --- a/src/MeshVS/MeshVS_DummySensitiveEntity.cxx +++ b/src/MeshVS/MeshVS_DummySensitiveEntity.cxx @@ -71,3 +71,21 @@ void MeshVS_DummySensitiveEntity::BVH() //================================================================ void MeshVS_DummySensitiveEntity::Clear() {} + +//======================================================================= +//function : HasInitLocation +//purpose : +//======================================================================= +Standard_Boolean MeshVS_DummySensitiveEntity::HasInitLocation() const +{ + return Standard_False; +} + +//======================================================================= +//function : InvInitLocation +//purpose : +//======================================================================= +inline gp_Trsf MeshVS_DummySensitiveEntity::InvInitLocation() const +{ + return gp_Trsf(); +} diff --git a/src/MeshVS/MeshVS_DummySensitiveEntity.hxx b/src/MeshVS/MeshVS_DummySensitiveEntity.hxx index 6e7402006b..f9101eefd1 100644 --- a/src/MeshVS/MeshVS_DummySensitiveEntity.hxx +++ b/src/MeshVS/MeshVS_DummySensitiveEntity.hxx @@ -48,6 +48,10 @@ public: Standard_EXPORT virtual void Clear() Standard_OVERRIDE; + Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE; + + Standard_EXPORT virtual gp_Trsf InvInitLocation() const Standard_OVERRIDE; + DEFINE_STANDARD_RTTI(MeshVS_DummySensitiveEntity) }; diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx index 208c9c66ab..703dc6fa3d 100755 --- a/src/QABugs/QABugs_19.cxx +++ b/src/QABugs/QABugs_19.cxx @@ -3866,6 +3866,118 @@ static Standard_Integer OCC24923( return 0; } +//======================================================================= +//function : OCC26195 +//purpose : +//======================================================================= +#include +#include +#include +#include +#include +#include +static Standard_Integer OCC26195 (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 3) + { + std::cerr << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + + if (ViewerTest::GetAISContext().IsNull()) + { + std::cerr << "Error: No opened context!\n"; + return 1; + } + + gp_Pnt2d aPxPnt1, aPxPnt2; + aPxPnt1.SetX (Draw::Atof (theArgVec[1])); + aPxPnt1.SetY (Draw::Atof (theArgVec[2])); + if (theArgNb > 4) + { + aPxPnt2.SetX (Draw::Atof (theArgVec[3])); + aPxPnt2.SetY (Draw::Atof (theArgVec[4])); + } + Standard_Boolean toPrint = Standard_False; + if (theArgNb % 2 == 0) + { + toPrint = Draw::Atoi (theArgVec[theArgNb - 1]); + } + + SelectMgr_SelectingVolumeManager* aMgr = new SelectMgr_SelectingVolumeManager(); + aMgr->SetActiveSelectionType (theArgNb > 4 ? + SelectMgr_SelectingVolumeManager::Box : SelectMgr_SelectingVolumeManager::Point); + 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); + } + const gp_Pnt* aVerts = aMgr->GetVertices(); + gp_Pnt aNearPnt = aMgr->GetNearPnt(); + gp_Pnt aFarPnt = aMgr->GetFarPnt(); + BRepBuilderAPI_MakePolygon aWireBldrs[4]; + + aWireBldrs[0].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z())); + aWireBldrs[0].Add (gp_Pnt (aVerts[4].X(), aVerts[4].Y(), aVerts[4].Z())); + aWireBldrs[0].Add (gp_Pnt (aVerts[6].X(), aVerts[6].Y(), aVerts[6].Z())); + aWireBldrs[0].Add (gp_Pnt (aVerts[2].X(), aVerts[2].Y(), aVerts[2].Z())); + aWireBldrs[0].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z())); + + aWireBldrs[1].Add (gp_Pnt (aVerts[4].X(), aVerts[4].Y(), aVerts[4].Z())); + aWireBldrs[1].Add (gp_Pnt (aVerts[5].X(), aVerts[5].Y(), aVerts[5].Z())); + aWireBldrs[1].Add (gp_Pnt (aVerts[7].X(), aVerts[7].Y(), aVerts[7].Z())); + aWireBldrs[1].Add (gp_Pnt (aVerts[6].X(), aVerts[6].Y(), aVerts[6].Z())); + aWireBldrs[1].Add (gp_Pnt (aVerts[4].X(), aVerts[4].Y(), aVerts[4].Z())); + + aWireBldrs[2].Add (gp_Pnt (aVerts[1].X(), aVerts[1].Y(), aVerts[1].Z())); + aWireBldrs[2].Add (gp_Pnt (aVerts[5].X(), aVerts[5].Y(), aVerts[5].Z())); + aWireBldrs[2].Add (gp_Pnt (aVerts[7].X(), aVerts[7].Y(), aVerts[7].Z())); + aWireBldrs[2].Add (gp_Pnt (aVerts[3].X(), aVerts[3].Y(), aVerts[3].Z())); + aWireBldrs[2].Add (gp_Pnt (aVerts[1].X(), aVerts[1].Y(), aVerts[1].Z())); + + aWireBldrs[3].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z())); + aWireBldrs[3].Add (gp_Pnt (aVerts[1].X(), aVerts[1].Y(), aVerts[1].Z())); + aWireBldrs[3].Add (gp_Pnt (aVerts[3].X(), aVerts[3].Y(), aVerts[3].Z())); + aWireBldrs[3].Add (gp_Pnt (aVerts[2].X(), aVerts[2].Y(), aVerts[2].Z())); + aWireBldrs[3].Add (gp_Pnt (aVerts[0].X(), aVerts[0].Y(), aVerts[0].Z())); + + TopoDS_Compound aComp; + BRep_Builder aCompBuilder; + aCompBuilder.MakeCompound (aComp); + for (Standard_Integer aWireIdx = 0; aWireIdx < 4; ++aWireIdx) + { + aCompBuilder.Add (aComp, aWireBldrs[aWireIdx].Shape()); + } + DBRep::Set ("c", aComp); + + Handle(AIS_InteractiveObject) aCmp = new AIS_Shape (aComp); + aCmp->SetColor (Quantity_NOC_GREEN); + ViewerTest::Display ("c", aCmp, Standard_True, Standard_True); + + Handle(Geom_CartesianPoint) aPnt1 = new Geom_CartesianPoint (aNearPnt); + Handle(Geom_CartesianPoint) aPnt2 = new Geom_CartesianPoint (aFarPnt); + + Handle(AIS_Line) aLine = new AIS_Line (aPnt1, aPnt2); + ViewerTest::Display ("l", aLine, Standard_True, Standard_True); + + if (toPrint) + { + theDI << "Near: " << aNearPnt.X() << " " << aNearPnt.Y() << " " << aNearPnt.Z() << "\n"; + theDI << "Far: " << aFarPnt.X() << " " << aFarPnt.Y() << " " << aFarPnt.Z() << "\n"; + } + + return 0; +} + void QABugs::Commands_19(Draw_Interpretor& theCommands) { const char *group = "QABugs"; @@ -3938,5 +4050,6 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) { theCommands.Add ("xprojponf", "xprojponf p f", __FILE__, xprojponf, group); theCommands.Add ("OCC24923", "OCC24923", __FILE__, OCC24923, group); theCommands.Add ("OCC26139", "OCC26139 [-boxsize value] [-boxgrid value] [-compgrid value]", __FILE__, OCC26139, group); + theCommands.Add ("OCC26195", "OCC26195 x1_pix y1_pix [x2_pix y2_pix] [toPrintPixelCoord 0|1]", __FILE__, OCC26195, group); return; } diff --git a/src/Select3D/Select3D_SensitiveBox.cxx b/src/Select3D/Select3D_SensitiveBox.cxx index ead44d99d3..1a32712efc 100644 --- a/src/Select3D/Select3D_SensitiveBox.cxx +++ b/src/Select3D/Select3D_SensitiveBox.cxx @@ -100,7 +100,7 @@ Standard_Boolean Select3D_SensitiveBox::Matches (SelectBasics_SelectingVolumeMan } Standard_Real aDepth; - if (!theMgr.Overlaps (myBox, aDepth)) // check for overlap + if (!theMgr.Overlaps (myBox.CornerMin(), myBox.CornerMax(), aDepth)) // check for overlap { return Standard_False; } diff --git a/src/Select3D/Select3D_SensitiveCircle.cxx b/src/Select3D/Select3D_SensitiveCircle.cxx index 3f8eaa23a5..cff276b500 100644 --- a/src/Select3D/Select3D_SensitiveCircle.cxx +++ b/src/Select3D/Select3D_SensitiveCircle.cxx @@ -108,7 +108,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent if (mySensType == Select3D_TOS_BOUNDARY) { - SetSensitivityFactor (6.0); + SetSensitivityFactor (6); } } @@ -166,7 +166,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectBasics_En if (mySensType == Select3D_TOS_BOUNDARY) { - SetSensitivityFactor (6.0); + SetSensitivityFactor (6); } } @@ -177,7 +177,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectBasics_En Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& theOwnerId, const Handle(TColgp_HArray1OfPnt)& thePnts3d, const Standard_Boolean theIsFilled) -: Select3D_SensitivePoly (theOwnerId, thePnts3d, !theIsFilled), +: Select3D_SensitivePoly (theOwnerId, thePnts3d, static_cast (!theIsFilled)), myStart (0), myEnd (0) { @@ -190,7 +190,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent if (mySensType == Select3D_TOS_BOUNDARY) { - SetSensitivityFactor (6.0); + SetSensitivityFactor (6); } } @@ -215,7 +215,7 @@ Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_Ent if (mySensType == Select3D_TOS_BOUNDARY) { - SetSensitivityFactor (6.0); + SetSensitivityFactor (6); } } @@ -256,9 +256,10 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume if (!theMgr.IsOverlapAllowed()) { thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG); - if (!theMgr.Overlaps (myBndBox.CornerMin(), myBndBox.CornerMax(), Standard_False)) + for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx) { - return Standard_False; + if (!theMgr.Overlaps (anArrayOfPnt->Value (aPntIdx))) + return Standard_False; } return Standard_True; } diff --git a/src/Select3D/Select3D_SensitiveCurve.cxx b/src/Select3D/Select3D_SensitiveCurve.cxx index 91951b4c31..a838f6b5de 100644 --- a/src/Select3D/Select3D_SensitiveCurve.cxx +++ b/src/Select3D/Select3D_SensitiveCurve.cxx @@ -32,7 +32,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti myCurve (theCurve) { loadPoints (theCurve, theNbPnts); - SetSensitivityFactor (3.0); + SetSensitivityFactor (3); } //================================================== @@ -44,7 +44,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti : Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True) { - SetSensitivityFactor (3.0); + SetSensitivityFactor (3); } //================================================== @@ -55,7 +55,7 @@ Select3D_SensitiveCurve::Select3D_SensitiveCurve (const Handle(SelectBasics_Enti const TColgp_Array1OfPnt& thePoints) : Select3D_SensitivePoly (theOwnerId, thePoints, Standard_True) { - SetSensitivityFactor (3.0); + SetSensitivityFactor (3); } //================================================== diff --git a/src/Select3D/Select3D_SensitiveEntity.cxx b/src/Select3D/Select3D_SensitiveEntity.cxx index 19f73a5ca5..fc19cd939b 100644 --- a/src/Select3D/Select3D_SensitiveEntity.cxx +++ b/src/Select3D/Select3D_SensitiveEntity.cxx @@ -25,10 +25,9 @@ IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveEntity, SelectBasics_SensitiveEntit //======================================================================= //function : Select3D_SensitiveEntity -//purpose : +//purpose : //======================================================================= - -Select3D_SensitiveEntity::Select3D_SensitiveEntity(const Handle(SelectBasics_EntityOwner)& theOwnerId) +Select3D_SensitiveEntity::Select3D_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId) : SelectBasics_SensitiveEntity (theOwnerId) {} //======================================================================= @@ -71,3 +70,22 @@ void Select3D_SensitiveEntity::Clear() { Set (NULL); } + +//======================================================================= +// function : HasInitLocation +// purpose : Returns true if the shape corresponding to the entity has init location +//======================================================================= +Standard_Boolean Select3D_SensitiveEntity::HasInitLocation() const +{ + return Standard_False; +} + +//======================================================================= +// function : InvInitLocation +// purpose : Returns inversed location transformation matrix if the shape corresponding +// to this entity has init location set. Otherwise, returns identity matrix. +//======================================================================= +gp_Trsf Select3D_SensitiveEntity::InvInitLocation() const +{ + return gp_Trsf(); +} diff --git a/src/Select3D/Select3D_SensitiveEntity.hxx b/src/Select3D/Select3D_SensitiveEntity.hxx index a235f15ad0..fe2a9e1f49 100644 --- a/src/Select3D/Select3D_SensitiveEntity.hxx +++ b/src/Select3D/Select3D_SensitiveEntity.hxx @@ -80,6 +80,13 @@ public: //! Clears up all resources and memory Standard_EXPORT virtual void Clear() Standard_OVERRIDE; + //! Returns true if the shape corresponding to the entity has init location + Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE; + + //! Returns inversed location transformation matrix if the shape corresponding + //! to this entity has init location set. Otherwise, returns identity matrix. + Standard_EXPORT virtual gp_Trsf InvInitLocation() const; + DEFINE_STANDARD_RTTI(Select3D_SensitiveEntity) protected: diff --git a/src/Select3D/Select3D_SensitivePoint.cxx b/src/Select3D/Select3D_SensitivePoint.cxx index 10bacb5d0f..214a65285c 100644 --- a/src/Select3D/Select3D_SensitivePoint.cxx +++ b/src/Select3D/Select3D_SensitivePoint.cxx @@ -29,7 +29,7 @@ Select3D_SensitivePoint::Select3D_SensitivePoint (const Handle(SelectBasics_Enti const gp_Pnt& thePoint) : Select3D_SensitiveEntity (theOwner) { - SetSensitivityFactor (12.0); + SetSensitivityFactor (12); myPoint = thePoint; } diff --git a/src/Select3D/Select3D_SensitivePoly.cxx b/src/Select3D/Select3D_SensitivePoly.cxx index ee3f9fe149..a89217619e 100644 --- a/src/Select3D/Select3D_SensitivePoly.cxx +++ b/src/Select3D/Select3D_SensitivePoly.cxx @@ -250,9 +250,8 @@ Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_Selecting { const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx); - Standard_Real aDummy; - return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), aDummy) - && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1), aDummy); + return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0)) + && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1)); } //================================================== diff --git a/src/Select3D/Select3D_SensitiveTriangle.cxx b/src/Select3D/Select3D_SensitiveTriangle.cxx index 7f43e7f5cf..eca050a620 100644 --- a/src/Select3D/Select3D_SensitiveTriangle.cxx +++ b/src/Select3D/Select3D_SensitiveTriangle.cxx @@ -54,10 +54,9 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu Standard_Real aDistToCOG = RealLast(); if (!theMgr.IsOverlapAllowed()) { - Standard_Real aDummy; - return theMgr.Overlaps (myPoints[0], aDummy) - && theMgr.Overlaps (myPoints[1], aDummy) - && theMgr.Overlaps (myPoints[2], aDummy); + return theMgr.Overlaps (myPoints[0]) + && theMgr.Overlaps (myPoints[1]) + && theMgr.Overlaps (myPoints[2]); } if (!theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDepth)) diff --git a/src/Select3D/Select3D_SensitiveTriangulation.cxx b/src/Select3D/Select3D_SensitiveTriangulation.cxx index c3973af13d..acfc0e248e 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.cxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.cxx @@ -56,6 +56,7 @@ Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(S myInitLocation (theInitLoc), myDetectedTr (-1) { + myInvInitLocation = myInitLocation.Transformation().Inverted(); mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY; const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles(); const TColgp_Array1OfPnt& aNodes = myTriangul->Nodes(); @@ -148,6 +149,7 @@ Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(S myFreeEdges (theFreeEdges), myDetectedTr (-1) { + myInvInitLocation = myInitLocation.Transformation().Inverted(); mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY; myPrimitivesNb = theIsInterior ? theTrg->Triangles().Length() : theFreeEdges->Length() / 2; myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1); @@ -187,19 +189,15 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer t Standard_Integer aPrimIdx = myBVHPrimIndexes->Value (theIdx); SelectMgr_Vec3 aMinPnt (RealLast()); SelectMgr_Vec3 aMaxPnt (RealFirst()); - Standard_Boolean hasInitLoc = HasInitLocation(); if (mySensType == Select3D_TOS_INTERIOR) { Standard_Integer aNode1, aNode2, aNode3; myTriangul->Triangles() (aPrimIdx + 1).Get (aNode1, aNode2, aNode3); - gp_Pnt aPnt1 = hasInitLoc ? myTriangul->Nodes().Value (aNode1).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNode1); - gp_Pnt aPnt2 = hasInitLoc ? myTriangul->Nodes().Value (aNode2).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNode2); - gp_Pnt aPnt3 = hasInitLoc ? myTriangul->Nodes().Value (aNode3).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNode3); + gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1); + gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2); + gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3); aMinPnt = SelectMgr_Vec3 (Min (aPnt1.X(), Min (aPnt2.X(), aPnt3.X())), Min (aPnt1.Y(), Min (aPnt2.Y(), aPnt3.Y())), @@ -212,10 +210,8 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer t { Standard_Integer aNodeIdx1 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx); Standard_Integer aNodeIdx2 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx + 1); - gp_Pnt aNode1 = hasInitLoc ? myTriangul->Nodes().Value (aNodeIdx1).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNodeIdx1); - gp_Pnt aNode2 = hasInitLoc ? myTriangul->Nodes().Value (aNodeIdx2).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNodeIdx2); + gp_Pnt aNode1 = myTriangul->Nodes().Value (aNodeIdx1); + gp_Pnt aNode2 = myTriangul->Nodes().Value (aNodeIdx2); aMinPnt = SelectMgr_Vec3 (Min (aNode1.X(), aNode2.X()), Min (aNode1.Y(), aNode2.Y()), @@ -266,17 +262,14 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_ Standard_Real& theMatchDepth) { const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx); - Standard_Boolean hasInitLoc = HasInitLocation(); if (mySensType == Select3D_TOS_BOUNDARY) { Standard_Integer aSegmStartIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 1); Standard_Integer aSegmEndIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 2); Handle(TColgp_HArray1OfPnt) anEdgePnts = new TColgp_HArray1OfPnt (1, 2); - gp_Pnt aSegmStart = hasInitLoc ? myTriangul->Nodes().Value (aSegmStartIdx).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aSegmStartIdx); - gp_Pnt aSegmEnd = hasInitLoc ? myTriangul->Nodes().Value (aSegmEndIdx).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aSegmEndIdx); + gp_Pnt aSegmStart = myTriangul->Nodes().Value (aSegmStartIdx); + gp_Pnt aSegmEnd = myTriangul->Nodes().Value (aSegmEndIdx); anEdgePnts->SetValue (1, aSegmStart); anEdgePnts->SetValue (2, aSegmEnd); Standard_Boolean isMatched = theMgr.Overlaps (anEdgePnts, Select3D_TOS_BOUNDARY, theMatchDepth); @@ -288,12 +281,9 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_ const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles(); Standard_Integer aNode1, aNode2, aNode3; aTriangles (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3); - gp_Pnt aPnt1 = hasInitLoc ? myTriangul->Nodes().Value (aNode1).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNode1); - gp_Pnt aPnt2 = hasInitLoc ? myTriangul->Nodes().Value (aNode2).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNode2); - gp_Pnt aPnt3 = hasInitLoc ? myTriangul->Nodes().Value (aNode3).Transformed (myInitLocation.Transformation()) - : myTriangul->Nodes().Value (aNode3); + gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1); + gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2); + gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3); return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, Select3D_TOS_INTERIOR, theMatchDepth); } } @@ -305,8 +295,6 @@ Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr, const Standard_Integer theElemIdx) { - Standard_Real aDummy; - const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx); if (mySensType == Select3D_TOS_BOUNDARY) @@ -314,13 +302,7 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_ gp_Pnt aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1)); gp_Pnt aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2)); - if (HasInitLocation()) // Note: Should be removed (by transforming frustum) - { - aSegmPnt1.Transform (myInitLocation.Transformation()); - aSegmPnt2.Transform (myInitLocation.Transformation()); - } - - return theMgr.Overlaps (aSegmPnt1, aDummy) && theMgr.Overlaps (aSegmPnt2, aDummy); + return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2); } else { @@ -334,16 +316,9 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_ gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2); gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3); - if (HasInitLocation()) // Note: Should be removed (by transforming frustum) - { - aPnt1.Transform (myInitLocation.Transformation()); - aPnt2.Transform (myInitLocation.Transformation()); - aPnt3.Transform (myInitLocation.Transformation()); - } - - return theMgr.Overlaps (aPnt1, aDummy) - && theMgr.Overlaps (aPnt2, aDummy) - && theMgr.Overlaps (aPnt3, aDummy); + return theMgr.Overlaps (aPnt1) + && theMgr.Overlaps (aPnt2) + && theMgr.Overlaps (aPnt3); } } @@ -390,7 +365,7 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::applyTransformation() gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(), aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(), aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z()); - aVertex.Transform (myInitLocation); + aVertex.Transform (myInitLocation.Transformation()); aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z())); } } @@ -431,7 +406,7 @@ Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox() //======================================================================= gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const { - return HasInitLocation() ? myCDG3D.Transformed (myInitLocation) : myCDG3D; + return myCDG3D; } //======================================================================= @@ -441,4 +416,22 @@ gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const Standard_Integer Select3D_SensitiveTriangulation::NbSubElements() { return myTriangul->Nodes().Length(); -} \ No newline at end of file +} + +//======================================================================= +//function : HasInitLocation +//purpose : +//======================================================================= +Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const +{ + return !myInitLocation.IsIdentity(); +} + +//======================================================================= +//function : InvInitLocation +//purpose : +//======================================================================= +gp_Trsf Select3D_SensitiveTriangulation::InvInitLocation() const +{ + return myInvInitLocation; +} diff --git a/src/Select3D/Select3D_SensitiveTriangulation.hxx b/src/Select3D/Select3D_SensitiveTriangulation.hxx index 537e05346f..f19b57ea74 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.hxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.hxx @@ -83,10 +83,6 @@ public: const Handle_Poly_Triangulation& Triangulation() const; - Standard_Boolean HasInitLocation() const; - - const TopLoc_Location& GetInitLocation() const; - //! Returns the length of array of triangles or edges Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE; @@ -110,6 +106,15 @@ public: //! is set, it will be applied Standard_EXPORT virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE; + //! Returns true if the shape corresponding to the entity has init location + Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE; + + //! Returns inversed location transformation matrix if the shape corresponding + //! to this entity has init location set. Otherwise, returns identity matrix. + Standard_EXPORT virtual gp_Trsf InvInitLocation() const Standard_OVERRIDE; + + inline const TopLoc_Location& GetInitLocation() const; + public: DEFINE_STANDARD_RTTI(Select3D_SensitiveTriangulation) @@ -134,20 +139,18 @@ private: virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr, const Standard_Integer theElemIdx) Standard_OVERRIDE; -public: - Standard_Real myBVHBuildTime; - private: Handle_Poly_Triangulation myTriangul; - TopLoc_Location myInitLocation; - gp_Pnt myCDG3D; //!< Center of the whole triangulation + TopLoc_Location myInitLocation; + gp_Pnt myCDG3D; //!< Center of the whole triangulation Handle_TColStd_HArray1OfInteger myFreeEdges; - Standard_Boolean mySensType; //!< Type of sensitivity: boundary or interior - Standard_Integer myDetectedTr; - Standard_Integer myPrimitivesNb; //!< Amount of free edges or triangles depending on sensitivity type + Standard_Boolean mySensType; //!< Type of sensitivity: boundary or interior + Standard_Integer myDetectedTr; + Standard_Integer myPrimitivesNb; //!< Amount of free edges or triangles depending on sensitivity type Handle_TColStd_HArray1OfInteger myBVHPrimIndexes; //!< Indexes of edges or triangles for BVH build - mutable Select3D_BndBox3d myBndBox; //!< Bounding box of the whole triangulation + mutable Select3D_BndBox3d myBndBox; //!< Bounding box of the whole triangulation + gp_Trsf myInvInitLocation; }; DEFINE_STANDARD_HANDLE(Select3D_SensitiveTriangulation, Select3D_SensitiveSet) diff --git a/src/Select3D/Select3D_SensitiveTriangulation.lxx b/src/Select3D/Select3D_SensitiveTriangulation.lxx index 4da21970c6..9898e4b1e8 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.lxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.lxx @@ -23,15 +23,6 @@ inline const Handle(Poly_Triangulation)& Select3D_SensitiveTriangulation::Triang return myTriangul; } -//======================================================================= -//function : HasInitLocation -//purpose : -//======================================================================= -inline Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const -{ - return !myInitLocation.IsIdentity(); -} - //======================================================================= //function : GetInitLocation //purpose : diff --git a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx index df795b5e34..480978e77c 100644 --- a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx +++ b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx @@ -17,8 +17,8 @@ #define _SelectBasics_SelectingVolumeManager_HeaderFile #include +#include #include -#include class Bnd_Box; class gp_Pnt; @@ -44,7 +44,8 @@ public: virtual Standard_Integer GetActiveSelectionType() const = 0; //! Returns true if selecting volume is overlapped by box theBox - virtual Standard_Boolean Overlaps (const BVH_Box& theBox, + virtual Standard_Boolean Overlaps (const NCollection_Vec3& theBoxMin, + const NCollection_Vec3& theBoxMax, Standard_Real& theDepth) = 0; //! Returns true if selecting volume is overlapped by axis-aligned bounding box with minimum @@ -53,10 +54,15 @@ public: const NCollection_Vec3& theBoxMax, Standard_Boolean* theInside = NULL) = 0; - //! Returns true if selecting volume is overlapped by point thePt - virtual Standard_Boolean Overlaps (const gp_Pnt& thePt, + //! Returns true if selecting volume is overlapped by point thePnt + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth) = 0; + //! Returns true if selecting volume is overlapped by point thePnt. + //! Does not perform depth calculation, so this method is defined as + //! helper function for inclusion test. + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) = 0; + //! Returns true if selecting volume is overlapped by planar convex polygon, which points //! are stored in theArrayOfPts, taking into account sensitivity type theSensType virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts, @@ -81,7 +87,7 @@ public: //! to the given point theCOG virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) = 0; - virtual NCollection_Vec3 DetectedPoint (const Standard_Real theDepth) const = 0; + virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const = 0; virtual Standard_Boolean IsOverlapAllowed() const = 0; diff --git a/src/SelectBasics/SelectBasics_SensitiveEntity.cdl b/src/SelectBasics/SelectBasics_SensitiveEntity.cdl index 185f60ca7e..c31e6b8a8b 100644 --- a/src/SelectBasics/SelectBasics_SensitiveEntity.cdl +++ b/src/SelectBasics/SelectBasics_SensitiveEntity.cdl @@ -19,7 +19,8 @@ deferred class SensitiveEntity from SelectBasics inherits TShared from MMgt ---Purpose: root class; the inheriting classes will be able to give -- sensitive Areas for the dynamic selection algorithms -uses +uses + Trsf from gp, EntityOwner, BndBox3d from Select3D, PickResult, @@ -29,7 +30,7 @@ is Initialize (theOwnerId : EntityOwner; - theSensFactor : Real from Standard = 2.0); + theSensFactor : Integer from Standard = 2); Set (me : mutable; theOwnerId : EntityOwner) @@ -55,7 +56,7 @@ is -- current selecting volume SensitivityFactor (me) - returns Real from Standard; + returns Integer from Standard; ---C++: inline ---Purpose: allows a better sensitivity for -- a specific entity in selection algorithms @@ -78,8 +79,20 @@ is Clear (me : mutable) is deferred; ---Purpose: Clears up all the resources and memory allocated + HasInitLocation (me) + returns Boolean from Standard + is deferred; + ---Purpose: Returns true if the shape corresponding to the entity + -- has init location. + + InvInitLocation (me) + returns Trsf from gp + is deferred; + ---Purpose: Returns inversed location transformation matrix if the shape corresponding + -- to this entity has init location set. Otherwise, returns identity matrix. + SetSensitivityFactor (me : mutable; - theSensFactor :Real from Standard) + theSensFactor : Integer from Standard) is protected; ---C++: inline ---Purpose: Allows to manage the sensitivity of the entity @@ -88,5 +101,5 @@ is fields myOwnerId : EntityOwner from SelectBasics is protected; - mySFactor : Real from Standard; + mySFactor : Integer from Standard; end SensitiveEntity; diff --git a/src/SelectBasics/SelectBasics_SensitiveEntity.cxx b/src/SelectBasics/SelectBasics_SensitiveEntity.cxx index d69189c957..b04aa82066 100644 --- a/src/SelectBasics/SelectBasics_SensitiveEntity.cxx +++ b/src/SelectBasics/SelectBasics_SensitiveEntity.cxx @@ -22,7 +22,7 @@ // purpose : Creates new empty sensitive entity instance //======================================================================= SelectBasics_SensitiveEntity::SelectBasics_SensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwnerId, - const Standard_Real theSensFactor) + const Standard_Integer theSensFactor) : myOwnerId (theOwnerId), mySFactor (theSensFactor) {} diff --git a/src/SelectBasics/SelectBasics_SensitiveEntity.lxx b/src/SelectBasics/SelectBasics_SensitiveEntity.lxx index 54df66f6ce..380ceb17fc 100644 --- a/src/SelectBasics/SelectBasics_SensitiveEntity.lxx +++ b/src/SelectBasics/SelectBasics_SensitiveEntity.lxx @@ -16,7 +16,7 @@ // function : SetSensitivityFactor // purpose : Allows to manage the sensitivity of the entity //======================================================================= -inline void SelectBasics_SensitiveEntity::SetSensitivityFactor (const Standard_Real theSensFactor) +inline void SelectBasics_SensitiveEntity::SetSensitivityFactor (const Standard_Integer theSensFactor) { mySFactor = theSensFactor; } @@ -25,7 +25,7 @@ inline void SelectBasics_SensitiveEntity::SetSensitivityFactor (const Standard_R // function : SensitivityFactor // purpose : Gets sensitivity factor for the entity //======================================================================= -inline Standard_Real SelectBasics_SensitiveEntity::SensitivityFactor() const +inline Standard_Integer SelectBasics_SensitiveEntity::SensitivityFactor() const { return mySFactor; } diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index 62d6de3de9..a59c6dabd3 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -68,7 +68,7 @@ void SelectMgr_BaseFrustum::SetViewport (const Standard_Real theX, // function : SetPixelTolerance // purpose : //======================================================================= -void SelectMgr_BaseFrustum::SetPixelTolerance (const Standard_Real theTol) +void SelectMgr_BaseFrustum::SetPixelTolerance (const Standard_Integer theTol) { myPixelTolerance = theTol; } @@ -97,7 +97,8 @@ void SelectMgr_BaseFrustum::SetBuilder (const Handle(SelectMgr_FrustumBuilder)& // purpose : SAT intersection test between defined volume and // given axis-aligned box //======================================================================= -Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const BVH_Box& /*theBndBox*/, +Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theBoxMin*/, + const SelectMgr_Vec3& /*theBoxMax*/, Standard_Real& /*theDepth*/) { return Standard_False; @@ -118,12 +119,21 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const SelectMgr_Vec3& /*theBox // function : Overlaps // purpose : Intersection test between defined volume and given point //======================================================================= -Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt*/, +Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt*/, Standard_Real& /*theDepth*/) { return Standard_False; } +//======================================================================= +// function : Overlaps +// purpose : Intersection test between defined volume and given point +//======================================================================= +Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt*/) +{ + return Standard_False; +} + //======================================================================= // function : Overlaps // purpose : SAT intersection test between defined volume and given @@ -131,7 +141,7 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt*/, // may be considered of interior part or boundary line defined // by segments depending on given sensitivity type //======================================================================= -Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& /*theArrayOfPts*/, +Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& /*theArrayOfPnts*/, Select3D_TypeOfSensitivity /*theSensType*/, Standard_Real& /*theDepth*/) { @@ -158,8 +168,8 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt1*/, // function : Overlaps // purpose : Checks if line segment overlaps selecting volume //======================================================================= -Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePt1*/, - const gp_Pnt& /*thePt2*/, +Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt1*/, + const gp_Pnt& /*thePnt2*/, Standard_Real& /*theDepth*/) { return Standard_False; @@ -175,9 +185,9 @@ Standard_Real SelectMgr_BaseFrustum::DistToGeometryCenter (const gp_Pnt& /*theCO return DBL_MAX; } -SelectMgr_Vec3 SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const +gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const { - return SelectMgr_Vec3 (RealLast()); + return gp_Pnt (RealLast(), RealLast(), RealLast()); } //======================================================================= diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index 0efa02be3b..1b3a5e6087 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -16,8 +16,6 @@ #ifndef _SelectMgr_BaseFrustum_HeaderFile #define _SelectMgr_BaseFrustum_HeaderFile -#include - #include #include @@ -56,7 +54,7 @@ public: const Graphic3d_Mat4d& theOrientation, const Standard_Integer theIsOrthographic); - void SetPixelTolerance (const Standard_Real theTol); + void SetPixelTolerance (const Standard_Integer theTol); void SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight); @@ -85,14 +83,19 @@ public: //! Builds selecting volumes set according to polyline points virtual void Build (const TColgp_Array1OfPnt2d& /*thePoints*/) {} - virtual NCollection_Handle Transform (const gp_Trsf& /*theTrsf*/) { return NULL; } - - //! IMPORTANT: Makes sense only for frustum built on a single point! + //! 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 - virtual NCollection_Handle Scale (const Standard_Real /*theScaleFactor*/) { return NULL; } + //! 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. + Standard_EXPORT virtual NCollection_Handle ScaleAndTransform (const Standard_Integer /*theScaleFactor*/, + const gp_Trsf& /*theTrsf*/) { return NULL; } //! SAT intersection test between defined volume and given axis-aligned box - virtual Standard_Boolean Overlaps (const BVH_Box& theBndBox, + virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, Standard_Real& theDepth); //! Returns true if selecting volume is overlapped by axis-aligned bounding box @@ -102,19 +105,25 @@ public: Standard_Boolean* theInside = NULL); //! Intersection test between defined volume and given point - virtual Standard_Boolean Overlaps (const gp_Pnt& thePt, + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth); + //! 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); + //! 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 - virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts, + virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth); //! Checks if line segment overlaps selecting frustum - virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, - const gp_Pnt& thePt2, + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, Standard_Real& theDepth); //! SAT intersection test between defined volume and given triangle. The test may @@ -130,7 +139,7 @@ public: //! screen point and given point theCOG virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG); - virtual SelectMgr_Vec3 DetectedPoint (const Standard_Real theDepth) const; + virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const; //! Checks if the point of sensitive in which selection was detected belongs //! to the region defined by clipping planes @@ -138,8 +147,8 @@ public: const Standard_Real theDepth); protected: - Standard_Real myPixelTolerance; //!< Pixel tolerance - Standard_Boolean myIsOrthographic; //!< Defines if current camera is orthographic + Standard_Integer myPixelTolerance; //!< Pixel tolerance + Standard_Boolean myIsOrthographic; //!< Defines if current camera is orthographic Handle(SelectMgr_FrustumBuilder) myBuilder; //!< A tool implementing methods for volume build }; diff --git a/src/SelectMgr/SelectMgr_Frustum.hxx b/src/SelectMgr/SelectMgr_Frustum.hxx index e5f9e1c8f2..b72d6a310d 100644 --- a/src/SelectMgr/SelectMgr_Frustum.hxx +++ b/src/SelectMgr/SelectMgr_Frustum.hxx @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include @@ -75,39 +77,39 @@ protected: //! SAT intersection test between frustum given and planar convex polygon represented as ordered point set Standard_Boolean hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, - SelectMgr_Vec3& theNormal); + gp_Vec& theNormal); //! SAT intersection test between defined volume and given triangle Standard_Boolean hasOverlap (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, const gp_Pnt& thePnt3, - SelectMgr_Vec3& theNormal); + gp_Vec& theNormal); private: //! Checks if AABB and frustum are separated along the given axis Standard_Boolean isSeparated (const SelectMgr_Vec3& theBoxMin, const SelectMgr_Vec3& theBoxMax, - const SelectMgr_Vec3& theDirect, + const gp_XYZ& theDirect, Standard_Boolean* theInside) const; //! Checks if triangle and frustum are separated along the given axis Standard_Boolean isSeparated (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, const gp_Pnt& thePnt3, - const SelectMgr_Vec3& theAxis) const; + const gp_XYZ& theAxis) const; protected: - SelectMgr_Vec3 myPlanes[N + 2]; //!< Plane equations - SelectMgr_Vec3 myVertices[N * 2]; //!< Vertices coordinates + gp_Vec myPlanes[N + 2]; //!< Plane equations + gp_Pnt myVertices[N * 2]; //!< Vertices coordinates Standard_Real myMaxVertsProjections[N + 2]; //!< Cached projections of vertices onto frustum plane directions Standard_Real myMinVertsProjections[N + 2]; //!< Cached projections of vertices onto frustum plane directions Standard_Real myMaxOrthoVertsProjections[3]; //!< Cached projections of vertices onto directions of ortho unit vectors Standard_Real myMinOrthoVertsProjections[3]; //!< Cached projections of vertices onto directions of ortho unit vectors - SelectMgr_Vec3 myEdgeDirs[6]; //!< Cached edge directions + gp_Vec myEdgeDirs[6]; //!< Cached edge directions }; #include diff --git a/src/SelectMgr/SelectMgr_Frustum.lxx b/src/SelectMgr/SelectMgr_Frustum.lxx index b2455229fb..2d5af3f56e 100644 --- a/src/SelectMgr/SelectMgr_Frustum.lxx +++ b/src/SelectMgr/SelectMgr_Frustum.lxx @@ -17,9 +17,6 @@ #include #include -#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z()) -#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z()) - // ======================================================================= // function : isSeparated // purpose : Checks if AABB and frustum are separated along the given axis. @@ -27,18 +24,18 @@ template Standard_Boolean SelectMgr_Frustum::isSeparated (const SelectMgr_Vec3& theBoxMin, const SelectMgr_Vec3& theBoxMax, - const SelectMgr_Vec3& theDirect, + const gp_XYZ& theDirect, Standard_Boolean* theInside) const { const Standard_Real aMinB = - theDirect.x() * (theDirect.x() < 0.0 ? theBoxMax.x() : theBoxMin.x()) + - theDirect.y() * (theDirect.y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) + - theDirect.z() * (theDirect.z() < 0.0 ? theBoxMax.z() : theBoxMin.z()); + theDirect.X() * (theDirect.X() < 0.0 ? theBoxMax.x() : theBoxMin.x()) + + theDirect.Y() * (theDirect.Y() < 0.0 ? theBoxMax.y() : theBoxMin.y()) + + theDirect.Z() * (theDirect.Z() < 0.0 ? theBoxMax.z() : theBoxMin.z()); const Standard_Real aMaxB = - theDirect.x() * (theDirect.x() < 0.0 ? theBoxMin.x() : theBoxMax.x()) + - theDirect.y() * (theDirect.y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) + - theDirect.z() * (theDirect.z() < 0.0 ? theBoxMin.z() : theBoxMax.z()); + theDirect.X() * (theDirect.X() < 0.0 ? theBoxMin.x() : theBoxMax.x()) + + theDirect.Y() * (theDirect.Y() < 0.0 ? theBoxMin.y() : theBoxMax.y()) + + theDirect.Z() * (theDirect.Z() < 0.0 ? theBoxMin.z() : theBoxMax.z()); Standard_ASSERT_RAISE (aMaxB >= aMinB, "Error! Failed to project box"); @@ -48,7 +45,7 @@ Standard_Boolean SelectMgr_Frustum::isSeparated (const SelectMgr_Vec3& theBox for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx) { - const Standard_Real aProj = DOT (myVertices[aVertIdx], theDirect); + const Standard_Real aProj = myVertices[aVertIdx].XYZ().Dot (theDirect); aMinF = Min (aMinF, aProj); aMaxF = Max (aMaxF, aProj); @@ -83,7 +80,7 @@ template Standard_Boolean SelectMgr_Frustum::isSeparated (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, const gp_Pnt& thePnt3, - const SelectMgr_Vec3& theAxis) const + const gp_XYZ& theAxis) const { // frustum projection Standard_Real aMinF = RealLast(); @@ -95,21 +92,21 @@ Standard_Boolean SelectMgr_Frustum::isSeparated (const gp_Pnt& thePnt1, Standard_Real aTriangleProj; - aTriangleProj = DOTp (theAxis, thePnt1); + aTriangleProj = theAxis.Dot (thePnt1.XYZ()); aMinTr = Min (aMinTr, aTriangleProj); aMaxTr = Max (aMaxTr, aTriangleProj); - aTriangleProj = DOTp (theAxis, thePnt2); + aTriangleProj = theAxis.Dot (thePnt2.XYZ()); aMinTr = Min (aMinTr, aTriangleProj); aMaxTr = Max (aMaxTr, aTriangleProj); - aTriangleProj = DOTp (theAxis, thePnt3); + aTriangleProj = theAxis.Dot (thePnt3.XYZ()); aMinTr = Min (aMinTr, aTriangleProj); aMaxTr = Max (aMaxTr, aTriangleProj); for (Standard_Integer aVertIter = 0; aVertIter < N * 2; ++aVertIter) { - const Standard_Real aProj = DOT (myVertices[aVertIter], theAxis); + const Standard_Real aProj = myVertices[aVertIter].XYZ().Dot (theAxis); aMinF = Min (aMinF, aProj); aMaxF = Max (aMaxF, aProj); @@ -152,17 +149,17 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const SelectMgr_Vec3& theMinP for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor) { - SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; + const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ(); const Standard_Real aBoxProjMin = - aPlane.x() * (aPlane.x() < 0.f ? theMaxPnt.x() : theMinPnt.x()) + - aPlane.y() * (aPlane.y() < 0.f ? theMaxPnt.y() : theMinPnt.y()) + - aPlane.z() * (aPlane.z() < 0.f ? theMaxPnt.z() : theMinPnt.z()); + aPlane.X() * (aPlane.X() < 0.f ? theMaxPnt.x() : theMinPnt.x()) + + aPlane.Y() * (aPlane.Y() < 0.f ? theMaxPnt.y() : theMinPnt.y()) + + aPlane.Z() * (aPlane.Z() < 0.f ? theMaxPnt.z() : theMinPnt.z()); const Standard_Real aBoxProjMax = - aPlane.x() * (aPlane.x() < 0.f ? theMinPnt.x() : theMaxPnt.x()) + - aPlane.y() * (aPlane.y() < 0.f ? theMinPnt.y() : theMaxPnt.y()) + - aPlane.z() * (aPlane.z() < 0.f ? theMinPnt.z() : theMaxPnt.z()); + aPlane.X() * (aPlane.X() < 0.f ? theMinPnt.x() : theMaxPnt.x()) + + aPlane.Y() * (aPlane.Y() < 0.f ? theMinPnt.y() : theMaxPnt.y()) + + aPlane.Z() * (aPlane.Z() < 0.f ? theMinPnt.z() : theMaxPnt.z()); Standard_ASSERT_RAISE (aBoxProjMax >= aBoxProjMin, "Error! Failed to project box"); @@ -180,13 +177,16 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const SelectMgr_Vec3& theMinP for (Standard_Integer aDim = 0; aDim < 3; ++aDim) { - SelectMgr_Vec3 anEdge1 (aDim == 0, aDim == 1, aDim == 2); - + // the following code performs a speedup of cross-product + // of vector with 1.0 at the position aDim and myEdgeDirs[aVolDir] + const Standard_Integer aNext = (aDim + 1) % 3; + const Standard_Integer aNextNext = (aDim + 2) % 3; for (Standard_Integer aVolDir = 0, aDirectionsNb = myIsOrthographic ? 4 : 6; aVolDir < aDirectionsNb; ++aVolDir) { - SelectMgr_Vec3 aDirection (anEdge1.y() * myEdgeDirs[aVolDir].z() - anEdge1.z() * myEdgeDirs[aVolDir].y(), - anEdge1.z() * myEdgeDirs[aVolDir].x() - anEdge1.x() * myEdgeDirs[aVolDir].z(), - anEdge1.x() * myEdgeDirs[aVolDir].y() - anEdge1.y() * myEdgeDirs[aVolDir].x()); + gp_XYZ aDirection (DBL_MAX, DBL_MAX, DBL_MAX); + aDirection.Ptr()[aDim] = 0; + aDirection.Ptr()[aNext] = -myEdgeDirs[aVolDir].XYZ().Ptr()[aNextNext]; + aDirection.Ptr()[aNextNext] = myEdgeDirs[aVolDir].XYZ().Ptr()[aNext]; if (isSeparated (theMinPnt, theMaxPnt, aDirection, theInside)) { @@ -209,11 +209,7 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& thePnt) for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor) { - const Select3D_Vec3& aPlane = myPlanes[aPlaneIdx]; - - const Standard_Real aPointProj = aPlane.x() * thePnt.X() + - aPlane.y() * thePnt.Y() + - aPlane.z() * thePnt.Z(); + const Standard_Real aPointProj = myPlanes[aPlaneIdx].XYZ().Dot (thePnt.XYZ()); if (aPointProj > myMaxVertsProjections[aPlaneIdx] || aPointProj < myMinVertsProjections[aPlaneIdx]) @@ -233,10 +229,8 @@ template Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& theStartPnt, const gp_Pnt& theEndPnt) { - const SelectMgr_Vec3& aDir = SelectMgr_Vec3 (theEndPnt.X() - theStartPnt.X(), - theEndPnt.Y() - theStartPnt.Y(), - theEndPnt.Z() - theStartPnt.Z()); - if (std::sqrt (aDir.x() * aDir.x() + aDir.y() * aDir.y() + aDir.z () * aDir.z()) < Precision::Confusion()) + const gp_XYZ& aDir = theEndPnt.XYZ() - theStartPnt.XYZ(); + if (aDir.Modulus() < Precision::Confusion()) return Standard_True; const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1; @@ -244,10 +238,9 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& theStartPnt, { Standard_Real aMinSegm = RealLast(), aMaxSegm = RealFirst(); Standard_Real aMinF = RealLast(), aMaxF = RealFirst(); - SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; - Standard_Real aProj1 = DOTp (aPlane, theStartPnt); - Standard_Real aProj2 = DOTp (aPlane, theEndPnt); + Standard_Real aProj1 = myPlanes[aPlaneIdx].XYZ().Dot (theStartPnt.XYZ()); + Standard_Real aProj2 = myPlanes[aPlaneIdx].XYZ().Dot (theEndPnt.XYZ()); aMinSegm = Min (aProj1, aProj2); aMaxSegm = Max (aProj1, aProj2); @@ -265,12 +258,12 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& theStartPnt, Standard_Real aMin2 = DBL_MAX, aMax2 = -DBL_MAX; for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx) { - Standard_Real aProjection = DOT (aDir, myVertices[aVertIdx]); + Standard_Real aProjection = aDir.Dot (myVertices[aVertIdx].XYZ()); aMax2 = Max (aMax2, aProjection); aMin2 = Min (aMin2, aProjection); } - Standard_Real aProj1 = DOTp (aDir, theStartPnt); - Standard_Real aProj2 = DOTp (aDir, theEndPnt); + Standard_Real aProj1 = aDir.Dot (theStartPnt.XYZ()); + Standard_Real aProj2 = aDir.Dot (theEndPnt.XYZ()); aMin1 = Min (aProj1, aProj2); aMax1 = Max (aProj1, aProj2); if (aMin1 > aMax2 @@ -285,18 +278,16 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& theStartPnt, Standard_Real aMinSegm = DBL_MAX, aMaxSegm = -DBL_MAX; Standard_Real aMinF = DBL_MAX, aMaxF = -DBL_MAX; - SelectMgr_Vec3 aTestDir = SelectMgr_Vec3 (aDir.y() * myEdgeDirs[aEdgeDirIdx].z() - aDir.z() * myEdgeDirs[aEdgeDirIdx].y(), - aDir.z() * myEdgeDirs[aEdgeDirIdx].x() - aDir.x() * myEdgeDirs[aEdgeDirIdx].z(), - aDir.x() * myEdgeDirs[aEdgeDirIdx].y() - aDir.y() * myEdgeDirs[aEdgeDirIdx].x()); + const gp_XYZ aTestDir = aDir.Crossed (myEdgeDirs[aEdgeDirIdx].XYZ()); - Standard_Real Proj1 = DOTp (aTestDir, theStartPnt); - Standard_Real Proj2 = DOTp (aTestDir, theEndPnt); + Standard_Real Proj1 = aTestDir.Dot (theStartPnt.XYZ()); + Standard_Real Proj2 = aTestDir.Dot (theEndPnt.XYZ()); aMinSegm = Min (Proj1, Proj2); aMaxSegm = Max (Proj1, Proj2); for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx) { - Standard_Real aProjection = DOT (aTestDir, myVertices[aVertIdx]); + Standard_Real aProjection = aTestDir.Dot (myVertices[aVertIdx].XYZ()); aMaxF = Max (aMaxF, aProjection); aMinF = Min (aMinF, aProjection); } @@ -318,26 +309,25 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& theStartPnt, // ======================================================================= template Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, - SelectMgr_Vec3& theNormal) + gp_Vec& theNormal) { Standard_Integer aStartIdx = theArrayOfPnts->Lower(); Standard_Integer anEndIdx = theArrayOfPnts->Upper(); - const gp_Pnt& aPnt1 = theArrayOfPnts->Value (aStartIdx); - const gp_Pnt& aPnt2 = theArrayOfPnts->Value (aStartIdx + 1); - const gp_Pnt& aPnt3 = theArrayOfPnts->Value (aStartIdx + 2); - const gp_XYZ aVec1 = aPnt1.XYZ() - aPnt2.XYZ(); - const gp_XYZ aVec2 = aPnt3.XYZ() - aPnt2.XYZ(); - theNormal = SelectMgr_Vec3 (aVec2.Y() * aVec1.Z() - aVec2.Z() * aVec1.Y(), - aVec2.Z() * aVec1.X() - aVec2.X() * aVec1.Z(), - aVec2.X() * aVec1.Y() - aVec2.Y() * aVec1.X()); - Standard_Real aPolygProjection = DOTp (theNormal, aPnt1); + const gp_XYZ& aPnt1 = theArrayOfPnts->Value (aStartIdx).XYZ(); + const gp_XYZ& aPnt2 = theArrayOfPnts->Value (aStartIdx + 1).XYZ(); + const gp_XYZ& aPnt3 = theArrayOfPnts->Value (aStartIdx + 2).XYZ(); + const gp_XYZ aVec1 = aPnt1 - aPnt2; + const gp_XYZ aVec2 = aPnt3 - aPnt2; + theNormal = aVec2.Crossed (aVec1); + const gp_XYZ& aNormal = theNormal.XYZ(); + Standard_Real aPolygProjection = aNormal.Dot (aPnt1); Standard_Real aMax = RealFirst(); Standard_Real aMin = RealLast(); for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx) { - Standard_Real aProjection = DOT (theNormal, myVertices[aVertIdx]); + Standard_Real aProjection = aNormal.Dot (myVertices[aVertIdx].XYZ()); aMax = Max (aMax, aProjection); aMin = Min (aMin, aProjection); } @@ -347,17 +337,17 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1Of return Standard_False; } - Standard_Integer aPlanesNb = N == 4 ? N + 2 : N + 1; - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < aPlanesNb; ++aPlaneIdx) + const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1; + for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor) { Standard_Real aMaxF = RealFirst(); Standard_Real aMinF = RealLast(); Standard_Real aMaxPolyg = RealFirst(); Standard_Real aMinPolyg = RealLast(); - SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; + const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ(); for (Standard_Integer aPntIter = aStartIdx; aPntIter <= anEndIdx; ++aPntIter) { - Standard_Real aProjection = DOTp (aPlane, theArrayOfPnts->Value (aPntIter)); + Standard_Real aProjection = aPlane.Dot (theArrayOfPnts->Value (aPntIter).XYZ()); aMaxPolyg = Max (aMaxPolyg, aProjection); aMinPolyg = Min (aMinPolyg, aProjection); } @@ -371,30 +361,28 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1Of } Standard_Integer aDirectionsNb = myIsOrthographic ? 4 : 6; - for (Standard_Integer aPntsIter = aStartIdx; aPntsIter <= anEndIdx; ++aPntsIter) + for (Standard_Integer aPntsIter = 0, aLastIdx = anEndIdx - aStartIdx, aLen = theArrayOfPnts->Length(); aPntsIter <= aLastIdx; ++aPntsIter) { - const gp_XYZ aSegmDir = aPntsIter == anEndIdx ? theArrayOfPnts->Value (aStartIdx).XYZ() - theArrayOfPnts->Value (anEndIdx).XYZ() - : theArrayOfPnts->Value (aPntsIter + 1).XYZ() - theArrayOfPnts->Value (aPntsIter).XYZ(); + const gp_XYZ aSegmDir = theArrayOfPnts->Value ((aPntsIter + 1) % aLen + aStartIdx).XYZ() + - theArrayOfPnts->Value (aPntsIter + aStartIdx).XYZ(); for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir) { Standard_Real aMaxPolyg = RealFirst(); Standard_Real aMinPolyg = RealLast(); Standard_Real aMaxF = RealFirst(); Standard_Real aMinF = RealLast(); - SelectMgr_Vec3 aTestDir = SelectMgr_Vec3 (aSegmDir.Y() * myEdgeDirs[aVolDir].z() - aSegmDir.Z() * myEdgeDirs[aVolDir].y(), - aSegmDir.Z() * myEdgeDirs[aVolDir].x() - aSegmDir.X() * myEdgeDirs[aVolDir].z(), - aSegmDir.X() * myEdgeDirs[aVolDir].y() - aSegmDir.Y() * myEdgeDirs[aVolDir].x()); + const gp_XYZ aTestDir = aSegmDir.Crossed (myEdgeDirs[aVolDir].XYZ()); for (Standard_Integer aPntIter = aStartIdx; aPntIter <= anEndIdx; ++aPntIter) { - Standard_Real aProjection = DOTp (aTestDir, theArrayOfPnts->Value (aPntIter)); + Standard_Real aProjection = aTestDir.Dot (theArrayOfPnts->Value (aPntIter).XYZ()); aMaxPolyg = Max (aMaxPolyg, aProjection); aMinPolyg = Min (aMinPolyg, aProjection); } for (Standard_Integer aVertIdx = 0; aVertIdx < N * 2; ++aVertIdx) { - Standard_Real aProjection = DOT (aTestDir, myVertices[aVertIdx]); + Standard_Real aProjection = aTestDir.Dot (myVertices[aVertIdx].XYZ()); aMaxF = Max (aMaxF, aProjection); aMinF = Min (aMinF, aProjection); } @@ -418,31 +406,27 @@ template Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, const gp_Pnt& thePnt3, - SelectMgr_Vec3& theNormal) + gp_Vec& theNormal) { - - SelectMgr_Vec3 aPnt1 (thePnt1.X(), thePnt1.Y(), thePnt1.Z()); - SelectMgr_Vec3 aPnt2 (thePnt2.X(), thePnt2.Y(), thePnt2.Z()); - SelectMgr_Vec3 aPnt3 (thePnt3.X(), thePnt3.Y(), thePnt3.Z()); - SelectMgr_Vec3 aTrEdges[3] = { aPnt2 - aPnt1, - aPnt3 - aPnt2, - aPnt1 - aPnt3 }; + const gp_XYZ aTrEdges[3] = { thePnt2.XYZ() - thePnt1.XYZ(), + thePnt3.XYZ() - thePnt2.XYZ(), + thePnt1.XYZ() - thePnt3.XYZ() }; const Standard_Integer anIncFactor = (myIsOrthographic && N == 4) ? 2 : 1; for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N + 1; aPlaneIdx += anIncFactor) { - SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; + const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ(); Standard_Real aTriangleProj; - aTriangleProj = DOT (aPlane, aPnt1); + aTriangleProj = aPlane.Dot (thePnt1.XYZ()); Standard_Real aTriangleProjMin = aTriangleProj; Standard_Real aTriangleProjMax = aTriangleProj; - aTriangleProj = DOT (aPlane, aPnt2); + aTriangleProj = aPlane.Dot (thePnt2.XYZ()); aTriangleProjMin = Min (aTriangleProjMin, aTriangleProj); aTriangleProjMax = Max (aTriangleProjMax, aTriangleProj); - aTriangleProj = DOT (aPlane, aPnt3); + aTriangleProj = aPlane.Dot (thePnt3.XYZ()); aTriangleProjMin = Min (aTriangleProjMin, aTriangleProj); aTriangleProjMax = Max (aTriangleProjMax, aTriangleProj); @@ -455,10 +439,8 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& thePnt1, } } - theNormal = SelectMgr_Vec3 (aTrEdges[2].y() * aTrEdges[0].z() - aTrEdges[2].z() * aTrEdges[0].y(), - aTrEdges[2].z() * aTrEdges[0].x() - aTrEdges[2].x() * aTrEdges[0].z(), - aTrEdges[2].x() * aTrEdges[0].y() - aTrEdges[2].y() * aTrEdges[0].x()); - if (isSeparated (thePnt1, thePnt2, thePnt3, theNormal)) + theNormal = aTrEdges[2].Crossed (aTrEdges[0]); + if (isSeparated (thePnt1, thePnt2, thePnt3, theNormal.XYZ())) { return Standard_False; } @@ -468,12 +450,7 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& thePnt1, { for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir) { - SelectMgr_Vec3 anEdge1 = myEdgeDirs[aVolDir]; - SelectMgr_Vec3 anEdge2 = aTrEdges[aTriangleEdgeIdx]; - SelectMgr_Vec3 aTestDirection = SelectMgr_Vec3 ( - anEdge1.y() * anEdge2.z() - anEdge1.z() * anEdge2.y(), - anEdge1.z() * anEdge2.x() - anEdge1.x() * anEdge2.z(), - anEdge1.x() * anEdge2.y() - anEdge1.y() * anEdge2.x()); + const gp_XYZ& aTestDirection = myEdgeDirs[aVolDir].XYZ().Crossed (aTrEdges[aTriangleEdgeIdx]); if (isSeparated (thePnt1, thePnt2, thePnt3, aTestDirection)) { @@ -484,6 +461,3 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& thePnt1, return Standard_True; } - -#undef DOT -#undef DOTp diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx index 91be420ac2..80a11e55ea 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx @@ -127,7 +127,7 @@ static NCollection_Vec4 safePointCast (const gp_Pnt& thePnt) // function : unProject // purpose : Unprojects point from NDC coords to 3d world space //======================================================================= -SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const +gp_Pnt SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const { Graphic3d_Mat4d aInvView; Graphic3d_Mat4d aInvProj; @@ -135,7 +135,7 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const // this case should never happen if (!myOrientation.Inverted (aInvView) || !myProjection.Inverted (aInvProj)) { - return SelectMgr_Vec3 (0.0, 0.0, 0.0); + return gp_Pnt (0.0, 0.0, 0.0); } // use compatible type of point @@ -146,7 +146,7 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w()); - return SelectMgr_Vec3 (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW); + return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW); } // ======================================================================= @@ -155,9 +155,9 @@ SelectMgr_Vec3 SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const // theZ = 0 - near plane, // theZ = 1 - far plane // ======================================================================= -SelectMgr_Vec3 SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& theX, - const Standard_Real& theY, - const Standard_Real& theZ) const +gp_Pnt SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& theX, + const Standard_Real& theY, + const Standard_Real& theZ) const { Standard_Real aX, anY, aZ; diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx index 8480454cea..e7ee1d8f5b 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx @@ -57,16 +57,16 @@ public: //! Projects 2d screen point onto view frustum plane: //! theZ = 0 - near plane, //! theZ = 1 - far plane - SelectMgr_Vec3 ProjectPntOnViewPlane (const Standard_Real& theX, - const Standard_Real& theY, - const Standard_Real& theZ) const; + gp_Pnt ProjectPntOnViewPlane (const Standard_Real& theX, + const Standard_Real& theY, + const Standard_Real& theZ) const; DEFINE_STANDARD_RTTI(SelectMgr_FrustumBuilder) private: //! Unprojects point from NDC coords to 3d world space - SelectMgr_Vec3 unProject (const gp_Pnt& thePnt) const; + gp_Pnt unProject (const gp_Pnt& thePnt) const; private: diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index bf658c9689..27b2d08978 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -18,11 +18,6 @@ #include -#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z()) -#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z()) -#define DISTANCE(A, B) (std::sqrt ((A.x() - B.x()) * (A.x() - B.x()) + (A.y() - B.y()) * (A.y() - B.y()) + (A.z() - B.z()) * (A.z() - B.z()))) -#define DISTANCEp(A, B) (std::sqrt ((A.x() - B.X()) * (A.x() - B.X()) + (A.y() - B.Y()) * (A.y() - B.Y()) + (A.z() - B.Z()) * (A.z() - B.Z()))) - // ======================================================================= // function : segmentSegmentDistance // purpose : @@ -31,18 +26,15 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP const gp_Pnt& theSegPnt2, Standard_Real& theDepth) { - SelectMgr_Vec3 anU = SelectMgr_Vec3 (theSegPnt2.X() - theSegPnt1.X(), - theSegPnt2.Y() - theSegPnt1.Y(), - theSegPnt2.Z() - theSegPnt1.Z()); - SelectMgr_Vec3 aV = myViewRayDir; - SelectMgr_Vec3 aW = SelectMgr_Vec3 (theSegPnt1.X() - myNearPickedPnt.x(), - theSegPnt1.Y() - myNearPickedPnt.y(), - theSegPnt1.Z() - myNearPickedPnt.z()); - Standard_Real anA = DOT (anU, anU); - Standard_Real aB = DOT (anU, aV); - Standard_Real aC = DOT (aV, aV); - Standard_Real aD = DOT (anU, aW); - Standard_Real anE = DOT (aV, aW); + gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ(); + gp_XYZ aV = myViewRayDir.XYZ(); + gp_XYZ aW = theSegPnt1.XYZ() - myNearPickedPnt.XYZ(); + + Standard_Real anA = anU.Dot (anU); + Standard_Real aB = anU.Dot (aV); + Standard_Real aC = aV.Dot (aV); + Standard_Real aD = anU.Dot (aW); + Standard_Real anE = aV.Dot (aW); Standard_Real aCoef = anA * aC - aB * aB; Standard_Real aSc, aSn, aSd = aCoef; Standard_Real aTc, aTn, aTd = aCoef; @@ -99,24 +91,22 @@ void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegP aSc = (Abs (aSn) < Precision::Confusion() ? 0.0 : aSn / aSd); aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd); - SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + myViewRayDir * aTc; - theDepth = DISTANCE (myNearPickedPnt, aClosestPnt); + gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc; + theDepth = myNearPickedPnt.Distance (aClosestPnt); } // ======================================================================= // function : segmentPlaneIntersection // purpose : // ======================================================================= -void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const SelectMgr_Vec3& thePlane, +void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePlane, const gp_Pnt& thePntOnPlane, Standard_Real& theDepth) { - SelectMgr_Vec3 anU = myViewRayDir; - SelectMgr_Vec3 aW = SelectMgr_Vec3 (myNearPickedPnt.x() - thePntOnPlane.X(), - myNearPickedPnt.y() - thePntOnPlane.Y(), - myNearPickedPnt.z() - thePntOnPlane.Z()); - Standard_Real aD = DOT (thePlane, anU); - Standard_Real aN = -DOT (thePlane, aW); + gp_XYZ anU = myViewRayDir.XYZ(); + gp_XYZ aW = myNearPickedPnt.XYZ() - thePntOnPlane.XYZ(); + Standard_Real aD = thePlane.Dot (anU); + Standard_Real aN = -thePlane.Dot (aW); if (Abs (aD) < Precision::Confusion()) { @@ -139,36 +129,144 @@ void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const SelectMgr_Vec return; } - SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + anU * aParam; - theDepth = DISTANCE (myNearPickedPnt, aClosestPnt); + gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + anU * aParam; + theDepth = myNearPickedPnt.Distance (aClosestPnt); } namespace { + // ======================================================================= + // function : computeFrustum + // purpose : Computes base frustum data: its vertices and edge directions + // ======================================================================= + void computeFrustum (const gp_Pnt2d theMinPnt, const gp_Pnt2d& theMaxPnt, + const Handle(SelectMgr_FrustumBuilder)& theBuilder, + gp_Pnt* theVertices, gp_Vec* theEdges) + { + // LeftTopNear + theVertices[0] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(), + theMaxPnt.Y(), + 0.0); + // LeftTopFar + theVertices[1] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(), + theMaxPnt.Y(), + 1.0); + // LeftBottomNear + theVertices[2] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(), + theMinPnt.Y(), + 0.0); + // LeftBottomFar + theVertices[3] = theBuilder->ProjectPntOnViewPlane (theMinPnt.X(), + theMinPnt.Y(), + 1.0); + // RightTopNear + theVertices[4] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), + theMaxPnt.Y(), + 0.0); + // RightTopFar + theVertices[5] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), + theMaxPnt.Y(), + 1.0); + // RightBottomNear + theVertices[6] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), + theMinPnt.Y(), + 0.0); + // RightBottomFar + theVertices[7] = theBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), + theMinPnt.Y(), + 1.0); + + // Horizontal + theEdges[0] = theVertices[4].XYZ() - theVertices[0].XYZ(); + // Vertical + theEdges[1] = theVertices[2].XYZ() - theVertices[0].XYZ(); + // LeftLower + theEdges[2] = theVertices[2].XYZ() - theVertices[3].XYZ(); + // RightLower + theEdges[3] = theVertices[6].XYZ() - theVertices[7].XYZ(); + // LeftUpper + theEdges[4] = theVertices[0].XYZ() - theVertices[1].XYZ(); + // RightUpper + theEdges[5] = theVertices[4].XYZ() - theVertices[5].XYZ(); + } + // ======================================================================= // function : computeNormals // purpose : Computes normals to frustum faces // ======================================================================= - void computeNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals) + void computeNormals (const gp_Vec* theEdges, gp_Vec* theNormals) { // Top - theNormals[0] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0], - theVertices[4] - theVertices[0]); + theNormals[0] = theEdges[0].Crossed (theEdges[4]); // Bottom - theNormals[1] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[2], - theVertices[6] - theVertices[2]); + theNormals[1] = theEdges[2].Crossed (theEdges[3]); // Left - theNormals[2] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0], - theVertices[2] - theVertices[0]); + theNormals[2] = theEdges[4].Crossed (theEdges[1]); // Right - theNormals[3] = SelectMgr_Vec3::Cross (theVertices[5] - theVertices[4], - theVertices[6] - theVertices[4]); + theNormals[3] = theEdges[5].Crossed (theEdges[3]); // Near - theNormals[4] = SelectMgr_Vec3::Cross (theVertices[6] - theVertices[4], - theVertices[0] - theVertices[4]); + theNormals[4] = theEdges[0].Crossed (theEdges[1]); // Far - theNormals[5] = SelectMgr_Vec3::Cross (theVertices[7] - theVertices[5], - theVertices[1] - theVertices[5]); + theNormals[5] = -theNormals[4]; + } +} + +// ======================================================================= +// function : cacheVertexProjections +// purpose : Caches projection of frustum's vertices onto its plane directions +// and {i, j, k} +// ======================================================================= +void SelectMgr_RectangularFrustum::cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum) +{ + if (theFrustum->myIsOrthographic) + { + // project vertices onto frustum normals + // Since orthographic view volume's faces are always a pairwise translation of + // one another, only 2 vertices that belong to opposite faces can be projected + // to simplify calculations. + Standard_Integer aVertIdxs[6] = { LeftTopNear, LeftBottomNear, // opposite planes in height direction + LeftBottomNear, RightBottomNear, // opposite planes in width direcion + LeftBottomFar, RightBottomNear }; // opposite planes in depth direction + for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; aPlaneIdx += 2) + { + Standard_Real aProj1 = theFrustum->myPlanes[aPlaneIdx].XYZ().Dot (theFrustum->myVertices[aVertIdxs[aPlaneIdx]].XYZ()); + Standard_Real aProj2 = theFrustum->myPlanes[aPlaneIdx].XYZ().Dot (theFrustum->myVertices[aVertIdxs[aPlaneIdx + 1]].XYZ()); + theFrustum->myMinVertsProjections[aPlaneIdx] = Min (aProj1, aProj2); + theFrustum->myMaxVertsProjections[aPlaneIdx] = Max (aProj1, aProj2); + } + } + else + { + // project all vertices onto frustum normals + for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx) + { + Standard_Real aMax = -DBL_MAX; + Standard_Real aMin = DBL_MAX; + const gp_XYZ& aPlane = theFrustum->myPlanes[aPlaneIdx].XYZ(); + for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) + { + Standard_Real aProjection = aPlane.Dot (theFrustum->myVertices[aVertIdx].XYZ()); + aMin = Min (aMin, aProjection); + aMax = Max (aMax, aProjection); + } + theFrustum->myMinVertsProjections[aPlaneIdx] = aMin; + theFrustum->myMaxVertsProjections[aPlaneIdx] = aMax; + } + } + + // project vertices onto {i, j, k} + for (Standard_Integer aDim = 0; aDim < 3; ++aDim) + { + Standard_Real aMax = -DBL_MAX; + Standard_Real aMin = DBL_MAX; + for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) + { + const gp_XYZ& aVert = theFrustum->myVertices[aVertIdx].XYZ(); + aMax = Max (aVert.Ptr()[aDim], aMax); + aMin = Min (aVert.Ptr()[aDim], aMin); + } + theFrustum->myMaxOrthoVertsProjections[aDim] = aMax; + theFrustum->myMinOrthoVertsProjections[aDim] = aMin; } } @@ -180,94 +278,24 @@ namespace void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint) { myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0); - myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0); - myViewRayDir = myFarPickedPnt - myNearPickedPnt; + myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0); + myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ(); myMousePos = thePoint; - // LeftTopNear - myVertices[0] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0, - thePoint.Y() + myPixelTolerance / 2.0, - 0.0); - // LeftTopFar - myVertices[1] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0, - thePoint.Y() + myPixelTolerance / 2.0, - 1.0); - // LeftBottomNear - myVertices[2] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0, - thePoint.Y() - myPixelTolerance / 2.0, - 0.0); - // LeftBottomFar - myVertices[3] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0, - thePoint.Y() - myPixelTolerance / 2.0, - 1.0); - // RightTopNear - myVertices[4] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0, - thePoint.Y() + myPixelTolerance / 2.0, - 0.0); - // RightTopFar - myVertices[5] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0, - thePoint.Y() + myPixelTolerance / 2.0, - 1.0); - // RightBottomNear - myVertices[6] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0, - thePoint.Y() - myPixelTolerance / 2.0, - 0.0); - // RightBottomFar - myVertices[7] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0, - thePoint.Y() - myPixelTolerance / 2.0, - 1.0); + 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 (myVertices, myPlanes); + computeNormals (myEdgeDirs, myPlanes); - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - myMaxVertsProjections[aPlaneIdx] = aMax; - myMinVertsProjections[aPlaneIdx] = aMin; - } - - SelectMgr_Vec3 aDimensions[3] = - { - SelectMgr_Vec3 (1.0, 0.0, 0.0), - SelectMgr_Vec3 (0.0, 1.0, 0.0), - SelectMgr_Vec3 (0.0, 0.0, 1.0) - }; - - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]); - aMax = Max (aProjection, aMax); - aMin = Min (aProjection, aMin); - } - myMaxOrthoVertsProjections[aDim] = aMax; - myMinOrthoVertsProjections[aDim] = aMin; - } - - // Horizontal - myEdgeDirs[0] = myVertices[4] - myVertices[0]; - // Vertical - myEdgeDirs[1] = myVertices[2] - myVertices[0]; - // LeftLower - myEdgeDirs[2] = myVertices[2] - myVertices[3]; - // RightLower - myEdgeDirs[3] = myVertices[6] - myVertices[7]; - // LeftUpper - myEdgeDirs[4] = myVertices[0] - myVertices[1]; - // RightUpper - myEdgeDirs[5] = myVertices[4] - myVertices[5]; + // compute vertices projections onto frustum normals and + // {i, j, k} vectors and store them to corresponding class fields + cacheVertexProjections (this); } // ======================================================================= @@ -283,278 +311,104 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt, myFarPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5, (theMinPnt.Y() + theMaxPnt.Y()) * 0.5, 1.0); - myViewRayDir = myFarPickedPnt - myNearPickedPnt; + myViewRayDir = myFarPickedPnt.XYZ() - myNearPickedPnt.XYZ(); - // LeftTopNear - myVertices[0] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(), - theMaxPnt.Y(), - 0.0); - // LeftTopFar - myVertices[1] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(), - theMaxPnt.Y(), - 1.0); - // LeftBottomNear - myVertices[2] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(), - theMinPnt.Y(), - 0.0); - // LeftBottomFar - myVertices[3] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(), - theMinPnt.Y(), - 1.0); - // RightTopNear - myVertices[4] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), - theMaxPnt.Y(), - 0.0); - // RightTopFar - myVertices[5] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), - theMaxPnt.Y(), - 1.0); - // RightBottomNear - myVertices[6] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), - theMinPnt.Y(), - 0.0); - // RightBottomFar - myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(), - theMinPnt.Y(), - 1.0); + // calculate base frustum characteristics: vertices and edge directions + computeFrustum (theMinPnt, theMaxPnt, myBuilder, myVertices, myEdgeDirs); // compute frustum normals - computeNormals (myVertices, myPlanes); + computeNormals (myEdgeDirs, myPlanes); - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - myMaxVertsProjections[aPlaneIdx] = aMax; - myMinVertsProjections[aPlaneIdx] = aMin; - } - - SelectMgr_Vec3 aDimensions[3] = - { - SelectMgr_Vec3 (1.0, 0.0, 0.0), - SelectMgr_Vec3 (0.0, 1.0, 0.0), - SelectMgr_Vec3 (0.0, 0.0, 1.0) - }; - - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - myMaxOrthoVertsProjections[aDim] = aMax; - myMinOrthoVertsProjections[aDim] = aMin; - } - - // Horizontal - myEdgeDirs[0] = myVertices[4] - myVertices[0]; - // Vertical - myEdgeDirs[1] = myVertices[2] - myVertices[0]; - // LeftLower - myEdgeDirs[2] = myVertices[2] - myVertices[3]; - // RightLower - myEdgeDirs[3] = myVertices[6] - myVertices[7]; - // LeftUpper - myEdgeDirs[4] = myVertices[0] - myVertices[1]; - // RightUpper - myEdgeDirs[5] = myVertices[4] - myVertices[5]; + // compute vertices projections onto frustum normals and + // {i, j, k} vectors and store them to corresponding class fields + cacheVertexProjections (this); } // ======================================================================= -// function : Transform -// purpose : Returns a copy of the frustum transformed according to the matrix given -// ======================================================================= -NCollection_Handle SelectMgr_RectangularFrustum::Transform (const gp_Trsf& theTrsf) -{ - SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum(); - - aRes->myNearPickedPnt = SelectMgr_MatOp::Transform (theTrsf, myNearPickedPnt); - aRes->myFarPickedPnt = SelectMgr_MatOp::Transform (theTrsf, myFarPickedPnt); - aRes->myViewRayDir = aRes->myFarPickedPnt - aRes->myNearPickedPnt; - - aRes->myIsOrthographic = myIsOrthographic; - - // LeftTopNear - aRes->myVertices[0] = SelectMgr_MatOp::Transform (theTrsf, myVertices[0]); - // LeftTopFar - aRes->myVertices[1] = SelectMgr_MatOp::Transform (theTrsf, myVertices[1]); - // LeftBottomNear - aRes->myVertices[2] = SelectMgr_MatOp::Transform (theTrsf, myVertices[2]); - // LeftBottomFar - aRes->myVertices[3] = SelectMgr_MatOp::Transform (theTrsf, myVertices[3]); - // RightTopNear - aRes->myVertices[4] = SelectMgr_MatOp::Transform (theTrsf, myVertices[4]); - // RightTopFar - aRes->myVertices[5] = SelectMgr_MatOp::Transform (theTrsf, myVertices[5]); - // RightBottomNear - aRes->myVertices[6] = SelectMgr_MatOp::Transform (theTrsf, myVertices[6]); - // RightBottomFar - aRes->myVertices[7] = SelectMgr_MatOp::Transform (theTrsf, myVertices[7]); - - // compute frustum normals - computeNormals (aRes->myVertices, aRes->myPlanes); - - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx]; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - aRes->myMaxVertsProjections[aPlaneIdx] = aMax; - aRes->myMinVertsProjections[aPlaneIdx] = aMin; - } - - SelectMgr_Vec3 aDimensions[3] = - { - SelectMgr_Vec3 (1.0, 0.0, 0.0), - SelectMgr_Vec3 (0.0, 1.0, 0.0), - SelectMgr_Vec3 (0.0, 0.0, 1.0) - }; - - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - aRes->myMaxOrthoVertsProjections[aDim] = aMax; - aRes->myMinOrthoVertsProjections[aDim] = aMin; - } - - // Horizontal - aRes->myEdgeDirs[0] = aRes->myVertices[4] - aRes->myVertices[0]; - // Vertical - aRes->myEdgeDirs[1] = aRes->myVertices[2] - aRes->myVertices[0]; - // LeftLower - aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[3]; - // RightLower - aRes->myEdgeDirs[3] = aRes->myVertices[6] - aRes->myVertices[7]; - // LeftUpper - aRes->myEdgeDirs[4] = aRes->myVertices[0] - aRes->myVertices[1]; - // RightUpper - aRes->myEdgeDirs[5] = aRes->myVertices[4] - aRes->myVertices[5]; - - return NCollection_Handle (aRes); -} - -// ======================================================================= -// function : Scale -// purpose : IMPORTANT: Makes sense only for frustum built on a single point! +// function : ScaleAndTransform +// purpose : 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. // ======================================================================= -NCollection_Handle SelectMgr_RectangularFrustum::Scale (const Standard_Real theScaleFactor) +NCollection_Handle SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_Trsf& theTrsf) { - SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum(); + Standard_ASSERT_RAISE (theScaleFactor > 0, + "Error! Pixel tolerance for selection should be greater than zero"); - aRes->myNearPickedPnt = myNearPickedPnt; - aRes->myFarPickedPnt = myFarPickedPnt; - aRes->myViewRayDir = myViewRayDir; + SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum(); + const Standard_Boolean isToScale = theScaleFactor != 1; + const Standard_Boolean isToTrsf = theTrsf.Form() != gp_Identity; + + if (!isToScale && !isToTrsf) + return aRes; aRes->myIsOrthographic = myIsOrthographic; + SelectMgr_RectangularFrustum* aRef = this; + + if (isToScale) + { + aRes->myNearPickedPnt = myNearPickedPnt; + 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); + + // recompute base frustum characteristics from scratch + computeFrustum (aMinPnt, aMaxPnt, myBuilder, aRes->myVertices, aRes->myEdgeDirs); + + aRef = aRes; + } + + if (isToTrsf) + { + aRes->myNearPickedPnt = aRef->myNearPickedPnt.Transformed (theTrsf); + aRes->myFarPickedPnt = aRef->myFarPickedPnt.Transformed (theTrsf); + aRes->myViewRayDir = aRes->myFarPickedPnt.XYZ() - aRes->myNearPickedPnt.XYZ(); + + // LeftTopNear + aRes->myVertices[0] = aRef->myVertices[0].Transformed (theTrsf); + // LeftTopFar + aRes->myVertices[1] = aRef->myVertices[1].Transformed (theTrsf); + // LeftBottomNear + aRes->myVertices[2] = aRef->myVertices[2].Transformed (theTrsf); + // LeftBottomFar + aRes->myVertices[3] = aRef->myVertices[3].Transformed (theTrsf); + // RightTopNear + aRes->myVertices[4] = aRef->myVertices[4].Transformed (theTrsf); + // RightTopFar + aRes->myVertices[5] = aRef->myVertices[5].Transformed (theTrsf); + // RightBottomNear + aRes->myVertices[6] = aRef->myVertices[6].Transformed (theTrsf); + // RightBottomFar + aRes->myVertices[7] = aRef->myVertices[7].Transformed (theTrsf); + + // Horizontal + aRes->myEdgeDirs[0] = aRes->myVertices[4].XYZ() - aRes->myVertices[0].XYZ(); + // Vertical + aRes->myEdgeDirs[1] = aRes->myVertices[2].XYZ() - aRes->myVertices[0].XYZ(); + // LeftLower + aRes->myEdgeDirs[2] = aRes->myVertices[2].XYZ() - aRes->myVertices[3].XYZ(); + // RightLower + aRes->myEdgeDirs[3] = aRes->myVertices[6].XYZ() - aRes->myVertices[7].XYZ(); + // LeftUpper + aRes->myEdgeDirs[4] = aRes->myVertices[0].XYZ() - aRes->myVertices[1].XYZ(); + // RightUpper + aRes->myEdgeDirs[5] = aRes->myVertices[4].XYZ() - aRes->myVertices[5].XYZ(); + } - // LeftTopNear - aRes->myVertices[0] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0, - myMousePos.Y() + theScaleFactor / 2.0, - 0.0); - // LeftTopFar - aRes->myVertices[1] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0, - myMousePos.Y() + theScaleFactor / 2.0, - 1.0); - // LeftBottomNear - aRes->myVertices[2] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0, - myMousePos.Y() - theScaleFactor / 2.0, - 0.0); - // LeftBottomFar - aRes->myVertices[3] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0, - myMousePos.Y() - theScaleFactor / 2.0, - 1.0); - // RightTopNear - aRes->myVertices[4] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0, - myMousePos.Y() + theScaleFactor / 2.0, - 0.0); - // RightTopFar - aRes->myVertices[5] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0, - myMousePos.Y() + theScaleFactor / 2.0, - 1.0); - // RightBottomNear - aRes->myVertices[6] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0, - myMousePos.Y() - theScaleFactor / 2.0, - 0.0); - // RightBottomFar - aRes->myVertices[7] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0, - myMousePos.Y() - theScaleFactor / 2.0, - 1.0); // compute frustum normals - computeNormals (aRes->myVertices, aRes->myPlanes); + computeNormals (aRes->myEdgeDirs, aRes->myPlanes); - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx]; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - aRes->myMaxVertsProjections[aPlaneIdx] = aMax; - aRes->myMinVertsProjections[aPlaneIdx] = aMin; - } - - SelectMgr_Vec3 aDimensions[3] = - { - SelectMgr_Vec3 (1.0, 0.0, 0.0), - SelectMgr_Vec3 (0.0, 1.0, 0.0), - SelectMgr_Vec3 (0.0, 0.0, 1.0) - }; - - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx) - { - Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - aRes->myMaxOrthoVertsProjections[aDim] = aMax; - aRes->myMinOrthoVertsProjections[aDim] = aMin; - } - - // Horizontal - aRes->myEdgeDirs[0] = aRes->myVertices[4] - aRes->myVertices[0]; - // Vertical - aRes->myEdgeDirs[1] = aRes->myVertices[2] - aRes->myVertices[0]; - // LeftLower - aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[3]; - // RightLower - aRes->myEdgeDirs[3] = aRes->myVertices[6] - aRes->myVertices[7]; - // LeftUpper - aRes->myEdgeDirs[4] = aRes->myVertices[0] - aRes->myVertices[1]; - // RightUpper - aRes->myEdgeDirs[5] = aRes->myVertices[4] - aRes->myVertices[5]; + cacheVertexProjections (aRes); return NCollection_Handle (aRes); } @@ -577,20 +431,19 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t // purpose : SAT intersection test between defined volume and // given axis-aligned box // ======================================================================= -Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const BVH_Box& theBox, +Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, Standard_Real& theDepth) { - const SelectMgr_Vec3& aMinPnt = theBox.CornerMin(); - const SelectMgr_Vec3& aMaxPnt = theBox.CornerMax(); - if (!hasOverlap (aMinPnt, aMaxPnt)) + if (!hasOverlap (theBoxMin, theBoxMax)) return Standard_False; - SelectMgr_Vec3 aNearestPnt = SelectMgr_Vec3 (RealLast(), RealLast(), RealLast()); - aNearestPnt.x() = Max (Min (myNearPickedPnt.x(), aMaxPnt.x()), aMinPnt.x()); - aNearestPnt.y() = Max (Min (myNearPickedPnt.y(), aMaxPnt.y()), aMinPnt.y()); - aNearestPnt.z() = Max (Min (myNearPickedPnt.z(), aMaxPnt.z()), aMinPnt.z()); + gp_Pnt aNearestPnt (RealLast(), RealLast(), RealLast()); + aNearestPnt.SetX (Max (Min (myNearPickedPnt.X(), theBoxMax.x()), theBoxMin.x())); + aNearestPnt.SetY (Max (Min (myNearPickedPnt.Y(), theBoxMax.y()), theBoxMin.y())); + aNearestPnt.SetZ (Max (Min (myNearPickedPnt.Z(), theBoxMax.z()), theBoxMin.z())); - theDepth = DISTANCE (aNearestPnt, myNearPickedPnt); + theDepth = aNearestPnt.Distance (myNearPickedPnt); return Standard_True; } @@ -605,15 +458,24 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt, if (!hasOverlap (thePnt)) return Standard_False; - SelectMgr_Vec3 aPnt (thePnt.X(), thePnt.Y(), thePnt.Z()); - SelectMgr_Vec3 aV = aPnt - myNearPickedPnt; - SelectMgr_Vec3 aDetectedPnt = myNearPickedPnt + myViewRayDir * (DOT (aV, myViewRayDir) / DOT (myViewRayDir, myViewRayDir)); + gp_XYZ aV = thePnt.XYZ() - myNearPickedPnt.XYZ(); + gp_Pnt aDetectedPnt = + myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * (aV.Dot (myViewRayDir.XYZ()) / myViewRayDir.Dot (myViewRayDir)); - theDepth = DISTANCE (aDetectedPnt, myNearPickedPnt); + theDepth = aDetectedPnt.Distance (myNearPickedPnt); return Standard_True; } +// ======================================================================= +// function : Overlaps +// purpose : Intersection test between defined volume and given point +// ======================================================================= +Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt) +{ + return hasOverlap (thePnt); +} + // ======================================================================= // function : Overlaps // purpose : Checks if line segment overlaps selecting frustum @@ -668,7 +530,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HAr } else if (theSensType == Select3D_TOS_INTERIOR) { - SelectMgr_Vec3 aPolyNorm (RealLast()); + gp_Vec aPolyNorm (gp_XYZ (RealLast(), RealLast(), RealLast())); if (!hasOverlap (theArrayOfPnts, aPolyNorm)) return Standard_False; @@ -704,48 +566,41 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, } else if (theSensType == Select3D_TOS_INTERIOR) { - SelectMgr_Vec3 aTriangleNormal (RealLast()); + gp_Vec aTriangleNormal (gp_XYZ (RealLast(), RealLast(), RealLast())); if (!hasOverlap (thePnt1, thePnt2, thePnt3, aTriangleNormal)) return Standard_False; // check if intersection point belongs to triangle's interior part - SelectMgr_Vec3 aPnt1 (thePnt1.X(), thePnt1.Y(), thePnt1.Z()); - SelectMgr_Vec3 aTrEdges[3] = { SelectMgr_Vec3 (thePnt2.X() - thePnt1.X(), thePnt2.Y() - thePnt1.Y(), thePnt2.Z() - thePnt1.Z()), - SelectMgr_Vec3 (thePnt3.X() - thePnt2.X(), thePnt3.Y() - thePnt2.Y(), thePnt3.Z() - thePnt2.Z()), - SelectMgr_Vec3 (thePnt1.X() - thePnt3.X(), thePnt1.Y() - thePnt3.Y(), thePnt1.Z() - thePnt3.Z()) }; - SelectMgr_Vec3 anEdge = (aPnt1 - myNearPickedPnt) * (1.0 / DOT (aTriangleNormal, myViewRayDir)); + gp_XYZ aTrEdges[3] = { thePnt2.XYZ() - thePnt1.XYZ(), + thePnt3.XYZ() - thePnt2.XYZ(), + thePnt1.XYZ() - thePnt3.XYZ() }; + gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / aTriangleNormal.Dot (myViewRayDir)); - Standard_Real aTime = DOT (aTriangleNormal, anEdge); + Standard_Real aTime = aTriangleNormal.Dot (anEdge); - SelectMgr_Vec3 aVec = SelectMgr_Vec3 (myViewRayDir.y() * anEdge.z() - myViewRayDir.z() * anEdge.y(), - myViewRayDir.z() * anEdge.x() - myViewRayDir.x() * anEdge.z(), - myViewRayDir.x() * anEdge.y() - myViewRayDir.y() * anEdge.x()); + gp_XYZ aVec = myViewRayDir.XYZ().Crossed (anEdge); - Standard_Real anU = DOT (aVec, aTrEdges[2]); - Standard_Real aV = DOT (aVec, aTrEdges[0]); + Standard_Real anU = aVec.Dot (aTrEdges[2]); + Standard_Real aV = aVec.Dot (aTrEdges[0]); Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0); if (isInterior) { - SelectMgr_Vec3 aDetectedPnt = myNearPickedPnt + myViewRayDir * aTime; - theDepth = DISTANCE (myNearPickedPnt, aDetectedPnt); + gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime; + theDepth = myNearPickedPnt.Distance (aDetectedPnt); return Standard_True; } gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3}; Standard_Real aMinDist = RealLast(); Standard_Integer aNearestEdgeIdx = -1; - SelectMgr_Vec3 aPtOnPlane = myNearPickedPnt + myViewRayDir * aTime; + gp_Pnt aPtOnPlane = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime; for (Standard_Integer anEdgeIdx = 0; anEdgeIdx < 3; ++anEdgeIdx) { - SelectMgr_Vec3 aW = SelectMgr_Vec3 (aPtOnPlane.x() - aPnts[anEdgeIdx].X(), - aPtOnPlane.y() - aPnts[anEdgeIdx].Y(), - aPtOnPlane.z() - aPnts[anEdgeIdx].Z()); - Standard_Real aCoef = DOT (aTrEdges[anEdgeIdx], aW) / DOT (aTrEdges[anEdgeIdx], aTrEdges[anEdgeIdx]); - Standard_Real aDist = DISTANCE (aPtOnPlane, SelectMgr_Vec3 (aPnts[anEdgeIdx].X() + aCoef * aTrEdges[anEdgeIdx].x(), - aPnts[anEdgeIdx].Y() + aCoef * aTrEdges[anEdgeIdx].y(), - aPnts[anEdgeIdx].Z() + aCoef * aTrEdges[anEdgeIdx].z())); + gp_XYZ aW = aPtOnPlane.XYZ() - aPnts[anEdgeIdx].XYZ(); + Standard_Real aCoef = aTrEdges[anEdgeIdx].Dot (aW) / aTrEdges[anEdgeIdx].Dot (aTrEdges[anEdgeIdx]); + Standard_Real aDist = aPtOnPlane.Distance (aPnts[anEdgeIdx].XYZ() + aCoef * aTrEdges[anEdgeIdx]); if (aMinDist > aDist) { aMinDist = aDist; @@ -765,8 +620,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, // ======================================================================= Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG) { - const SelectMgr_Vec3& aCOG = SelectMgr_Vec3 (theCOG.X(), theCOG.Y(), theCOG.Z()); - return DISTANCE (aCOG, myNearPickedPnt); + return theCOG.Distance (myNearPickedPnt); } // ======================================================================= @@ -774,9 +628,9 @@ Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& // purpose : Calculates the point on a view ray that was detected during // the run of selection algo by given depth // ======================================================================= -SelectMgr_Vec3 SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const +gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const { - return myNearPickedPnt + myViewRayDir * theDepth; + return myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * theDepth; } // ======================================================================= @@ -803,8 +657,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ(); - Standard_Real aDotProduct = DOTp (myViewRayDir, aPlaneDirXYZ); - Standard_Real aDistance = - (DOTp (myNearPickedPnt, aPlaneDirXYZ) + aPlaneD); + Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ); + Standard_Real aDistance = - myNearPickedPnt.XYZ().Dot (aPlaneDirXYZ) + + aPlaneD; // check whether the pick line is parallel to clip plane if (Abs (aDotProduct) < Precision::Angular()) @@ -823,8 +678,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen continue; } - const SelectMgr_Vec3 anIntersectionPt = myNearPickedPnt + myViewRayDir * aParam; - const Standard_Real aDistToPln = DISTANCE (anIntersectionPt, myNearPickedPnt); + const gp_Pnt anIntersectionPt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam; + const Standard_Real aDistToPln = anIntersectionPt.Distance (myNearPickedPnt); // change depth limits for case of opposite and directed planes if (aDotProduct < 0.0) diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index ef97920ceb..5570f4db44 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -42,18 +42,22 @@ public: virtual void Build (const gp_Pnt2d& theMinPnt, const gp_Pnt2d& theMaxPnt) Standard_OVERRIDE; - //! Returns a copy of the frustum transformed according to the matrix given - virtual NCollection_Handle Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE; - - //! IMPORTANT: Makes sense only for frustum built on a single point! + //! 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 - virtual NCollection_Handle Scale (const Standard_Real theScaleFactor) Standard_OVERRIDE; + //! 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 NCollection_Handle ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_Trsf& theTrsf) Standard_OVERRIDE; // SAT Tests for different objects //! SAT intersection test between defined volume and given axis-aligned box - virtual Standard_Boolean Overlaps (const BVH_Box& theBox, + virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, Standard_Real& theDepth) Standard_OVERRIDE; //! Returns true if selecting volume is overlapped by axis-aligned bounding box @@ -66,6 +70,9 @@ public: virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth) Standard_OVERRIDE; + //! Intersection test between defined volume and given point + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) 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 //! boundary line defined by segments depending on given sensitivity type @@ -92,29 +99,45 @@ public: virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) Standard_OVERRIDE; //! Calculates the point on a view ray that was detected during the run of selection algo by given depth - virtual SelectMgr_Vec3 DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE; + virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE; //! Checks if the point of sensitive in which selection was detected belongs //! to the region defined by clipping planes virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes, const Standard_Real theDepth) Standard_OVERRIDE; + //! A set of helper functions that return rectangular selecting frustum data + inline const gp_Pnt* GetVertices() const { return myVertices; } + + inline gp_Pnt GetNearPnt() const { return myNearPickedPnt; } + + inline gp_Pnt GetFarPnt() const { return myFarPickedPnt; } protected: void segmentSegmentDistance (const gp_Pnt& theSegPnt1, const gp_Pnt& theSegPnt2, Standard_Real& theDepth); - void segmentPlaneIntersection (const SelectMgr_Vec3& thePlane, + void segmentPlaneIntersection (const gp_Vec& thePlane, const gp_Pnt& thePntOnPlane, Standard_Real& theDepth); private: - SelectMgr_Vec3 myNearPickedPnt; //!< 3d projection of user-picked selection point onto near view plane - SelectMgr_Vec3 myFarPickedPnt; //!< 3d projection of user-picked selection point onto far view plane - SelectMgr_Vec3 myViewRayDir; - gp_Pnt2d myMousePos; //!< Mouse coordinates + void cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum); + +private: + enum { LeftTopNear, LeftTopFar, + LeftBottomNear, LeftBottomFar, + RightTopNear, RightTopFar, + RightBottomNear, RightBottomFar }; + +private: + + 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_Vec myViewRayDir; + gp_Pnt2d myMousePos; //!< Mouse coordinates }; #endif // _SelectMgr_RectangularFrustum_HeaderFile diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx index 91bc2632f1..5018d5789c 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx @@ -25,7 +25,7 @@ //======================================================================= SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet() { - myBuilder = new BVH_BinnedBuilder (1, 32, Standard_False); + myBuilder = new BVH_BinnedBuilder (1, 32, Standard_True); } //======================================================================= diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index aa1ff3ba70..64d538a538 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -32,10 +32,19 @@ SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boo } //======================================================================= -// function : Transform -// purpose : Returns a copy of active frustum transformed according to the matrix given +// function : ScaleAndTransform +// purpose : 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. //======================================================================= -SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Transform (const gp_Trsf& theTrsf) +SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_Trsf& theTrsf) { SelectMgr_SelectingVolumeManager aMgr (Standard_False); @@ -44,31 +53,13 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Transform (co aMgr.myActiveSelectionType = myActiveSelectionType; - aMgr.mySelectingVolumes[myActiveSelectionType / 2] = mySelectingVolumes[myActiveSelectionType / 2]->Transform (theTrsf); + aMgr.mySelectingVolumes[myActiveSelectionType / 2] + = mySelectingVolumes[myActiveSelectionType / 2]->ScaleAndTransform (theScaleFactor, theTrsf); aMgr.myToAllowOverlap = myToAllowOverlap; return aMgr; } -//======================================================================= -// function : Scale -// purpose : IMPORTANT: Makes sense only for point selection! -// Returns a copy of the frustum resized according to the scale factor given -//======================================================================= -SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Scale (const Standard_Real theScaleFactor) -{ - if (myActiveSelectionType != Point) - return SelectMgr_SelectingVolumeManager (Standard_False); - - SelectMgr_SelectingVolumeManager aMgr (Standard_False); - - aMgr.myActiveSelectionType = Point; - - aMgr.mySelectingVolumes[Point] = mySelectingVolumes[Point]->Scale (theScaleFactor); - - return aMgr; -} - //======================================================================= // function : GetActiveSelectionType // purpose : @@ -147,7 +138,7 @@ void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer the // function : SetPixelTolerance // purpose : Updates pixel tolerance in all selecting volumes //======================================================================= -void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Real theTolerance) +void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance) { for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx) { @@ -198,13 +189,14 @@ void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1 // purpose : SAT intersection test between defined volume and // given axis-aligned box //======================================================================= -Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const BVH_Box& theBndBox, +Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, Standard_Real& theDepth) { if (myActiveSelectionType == Unknown) return Standard_False; - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox, theDepth); + return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theDepth); } //======================================================================= @@ -225,16 +217,28 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec // function : Overlaps // purpose : Intersection test between defined volume and given point //======================================================================= -Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt, +Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth) { if (myActiveSelectionType == Unknown) return Standard_False; - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt, + return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt, theDepth); } +//======================================================================= +// function : Overlaps +// purpose : Intersection test between defined volume and given point +//======================================================================= +Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt) +{ + if (myActiveSelectionType == Unknown) + return Standard_False; + + return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt); +} + //======================================================================= // function : Overlaps // purpose : SAT intersection test between defined volume and given @@ -242,14 +246,14 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt // may be considered of interior part or boundary line defined // by segments depending on given sensitivity type //======================================================================= -Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts, +Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, Standard_Integer theSensType, Standard_Real& theDepth) { if (myActiveSelectionType == Unknown) return Standard_False; - return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPts, + return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts, (Select3D_TypeOfSensitivity)theSensType, theDepth); } @@ -310,10 +314,10 @@ Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_P // the run of selection algo by given depth. Is valid for point // selection only // ======================================================================= -NCollection_Vec3 SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const +gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const { if (myActiveSelectionType != Point) - return NCollection_Vec3 (RealLast()); + return gp_Pnt (RealLast(), RealLast(), RealLast()); return mySelectingVolumes[Frustum]->DetectedPoint (theDepth); } @@ -351,3 +355,45 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const { return myActiveSelectionType != Box || myToAllowOverlap; } + +//======================================================================= +// function : GetVertices +// purpose : +//======================================================================= +const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const +{ + if (myActiveSelectionType == Polyline) + return NULL; + + const SelectMgr_RectangularFrustum* aFr = + reinterpret_cast (mySelectingVolumes[myActiveSelectionType / 2].Access()); + return aFr->GetVertices(); +} + +//======================================================================= +// function : GetNearPnt +// purpose : +//======================================================================= +gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPnt() const +{ + if (myActiveSelectionType == Polyline) + return gp_Pnt(); + + const SelectMgr_RectangularFrustum* aFr = + reinterpret_cast (mySelectingVolumes[myActiveSelectionType / 2].Access()); + return aFr->GetNearPnt(); +} + +//======================================================================= +// function : GetFarPnt +// purpose : +//======================================================================= +gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPnt() const +{ + if (myActiveSelectionType == Polyline) + return gp_Pnt(); + + const SelectMgr_RectangularFrustum* aFr = + reinterpret_cast (mySelectingVolumes[myActiveSelectionType / 2].Access()); + return aFr->GetFarPnt(); +} diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 6c6a7d7238..a14ba9137f 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -37,12 +37,16 @@ public: Standard_EXPORT virtual ~SelectMgr_SelectingVolumeManager() {}; - //! Returns a copy of active frustum transformed according to the matrix given - Standard_EXPORT virtual SelectMgr_SelectingVolumeManager Transform (const gp_Trsf& theTrsf); - - //! IMPORTANT: Makes sense only for point selection! + //! 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 - Standard_EXPORT virtual SelectMgr_SelectingVolumeManager Scale (const Standard_Real theScaleFactor); + //! 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. + Standard_EXPORT virtual SelectMgr_SelectingVolumeManager ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_Trsf& theTrsf); Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE; @@ -63,7 +67,7 @@ public: const Standard_Real theHeight); //! Updates pixel tolerance in all selecting volumes - Standard_EXPORT void SetPixelTolerance (const Standard_Real theTolerance); + Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTolerance); //! Updates window size in all selecting volumes Standard_EXPORT void SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight); @@ -81,7 +85,8 @@ public: //! SAT intersection test between defined volume and given axis-aligned box - Standard_EXPORT virtual Standard_Boolean Overlaps (const BVH_Box& theBndBox, + Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, + const SelectMgr_Vec3& theBoxMax, Standard_Real& theDepth) Standard_OVERRIDE; //! Returns true if selecting volume is overlapped by axis-aligned bounding box @@ -91,9 +96,12 @@ public: Standard_Boolean* theInside = NULL) Standard_OVERRIDE; //! Intersection test between defined volume and given point - Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt, + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth) Standard_OVERRIDE; + //! Intersection test between defined volume and given point + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt) 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 //! boundary line defined by segments depending on given sensitivity type @@ -102,16 +110,16 @@ public: Standard_Real& theDepth) Standard_OVERRIDE; //! Checks if line segment overlaps selecting frustum - Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, - const gp_Pnt& thePt2, + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, Standard_Real& theDepth) 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 //! depending on given sensitivity type - Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, - const gp_Pnt& thePt2, - const gp_Pnt& thePt3, + Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + const gp_Pnt& thePnt3, Standard_Integer theSensType, Standard_Real& theDepth) Standard_OVERRIDE; @@ -122,7 +130,7 @@ public: //! Calculates the point on a view ray that was detected during the run of selection algo by given depth. Is valid for point //! selection only - Standard_EXPORT virtual NCollection_Vec3 DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE; + Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE; //! Checks if the point of sensitive in which selection was detected belongs //! to the region defined by clipping planes @@ -136,6 +144,13 @@ public: Standard_EXPORT virtual Standard_Boolean IsOverlapAllowed() const Standard_OVERRIDE; + //! A set of helper functions that return rectangular selecting frustum data + Standard_EXPORT const gp_Pnt* GetVertices() const; + + Standard_EXPORT gp_Pnt GetNearPnt() const; + + Standard_EXPORT gp_Pnt GetFarPnt() const; + private: enum { Frustum, FrustumSet, VolumeTypesNb }; //!< Defines the amount of available selecting volumes diff --git a/src/SelectMgr/SelectMgr_Selection.cxx b/src/SelectMgr/SelectMgr_Selection.cxx index ad5e55eaa8..4bfb2a8dd0 100644 --- a/src/SelectMgr/SelectMgr_Selection.cxx +++ b/src/SelectMgr/SelectMgr_Selection.cxx @@ -29,7 +29,7 @@ SelectMgr_Selection::SelectMgr_Selection (const Standard_Integer theModeIdx) : myMode (theModeIdx), mySelectionState (SelectMgr_SOS_Unknown), myBVHUpdateStatus (SelectMgr_TBU_None), - mySensFactor (2.0) + mySensFactor (2) {} SelectMgr_Selection::~SelectMgr_Selection() @@ -48,7 +48,7 @@ void SelectMgr_Selection::Destroy() Handle(SelectMgr_SensitiveEntity)& anEntity = myEntities.ChangeValue (anEntityIdx); anEntity->BaseSensitive()->Set (NULL); } - mySensFactor = 2.0; + mySensFactor = 2; } //================================================== @@ -134,7 +134,7 @@ void SelectMgr_Selection::SetSelectionState (const SelectMgr_StateOfSelection th // function: Sensitivity // purpose : Returns sensitivity of the selection //================================================== -Standard_Real SelectMgr_Selection::Sensitivity() const +Standard_Integer SelectMgr_Selection::Sensitivity() const { return mySensFactor; } diff --git a/src/SelectMgr/SelectMgr_Selection.hxx b/src/SelectMgr/SelectMgr_Selection.hxx index 8a2c0b4eda..1536b68a36 100644 --- a/src/SelectMgr/SelectMgr_Selection.hxx +++ b/src/SelectMgr/SelectMgr_Selection.hxx @@ -131,7 +131,7 @@ public: Standard_EXPORT void SetSelectionState (const SelectMgr_StateOfSelection theState) const; //! Returns sensitivity of the selection - Standard_EXPORT Standard_Real Sensitivity() const; + Standard_EXPORT Standard_Integer Sensitivity() const; DEFINE_STANDARD_RTTI (SelectMgr_Selection) @@ -148,7 +148,7 @@ private: SelectMgr_TypeOfUpdate myUpdateStatus; mutable SelectMgr_StateOfSelection mySelectionState; mutable SelectMgr_TypeOfBVHUpdate myBVHUpdateStatus; - Standard_Real mySensFactor; + Standard_Integer mySensFactor; }; DEFINE_STANDARD_HANDLE(SelectMgr_Selection, MMgt_TShared) diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx index 696168d121..b3c348dc90 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx @@ -15,10 +15,6 @@ #include -#define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z()) -#define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z()) -#define LENGTH(A) (std::sqrt (A.x() * A.x() + A.y() * A.y() + A.z() * A.z())) - SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum() { Clear(); @@ -26,23 +22,55 @@ SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum() namespace { - void computeFrustumNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals) + void computeFrustumNormals (const gp_Vec* theEdges, gp_Vec* theNormals) { // V0V1 - theNormals[0] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[0], - theVertices[4] - theVertices[0]); + theNormals[0] = theEdges[0].Crossed (theEdges[1]); // V1V2 - theNormals[1] = SelectMgr_Vec3::Cross (theVertices[4] - theVertices[1], - theVertices[5] - theVertices[1]); + theNormals[1] = theEdges[1].Crossed (theEdges[2]); // V0V2 - theNormals[2] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[0], - theVertices[5] - theVertices[0]); + theNormals[2] = theEdges[0].Crossed (theEdges[2]); // Near - theNormals[3] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0], - theVertices[2] - theVertices[0]); + theNormals[3] = theEdges[3].Crossed (theEdges[5]); // Far - theNormals[4] = SelectMgr_Vec3::Cross (theVertices[4] - theVertices[3], - theVertices[5] - theVertices[3]); + theNormals[4] = -theNormals[3]; + } +} + +// ======================================================================= +// function : cacheVertexProjections +// purpose : Caches projection of frustum's vertices onto its plane directions +// and {i, j, k} +// ======================================================================= +void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) +{ + for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx) + { + Standard_Real aMax = -DBL_MAX; + Standard_Real aMin = DBL_MAX; + const gp_XYZ& aPlane = theFrustum->myPlanes[aPlaneIdx].XYZ(); + for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) + { + Standard_Real aProjection = aPlane.Dot (theFrustum->myVertices[aVertIdx].XYZ()); + aMax = Max (aMax, aProjection); + aMin = Min (aMin, aProjection); + } + theFrustum->myMaxVertsProjections[aPlaneIdx] = aMax; + theFrustum->myMinVertsProjections[aPlaneIdx] = aMin; + } + + for (Standard_Integer aDim = 0; aDim < 3; ++aDim) + { + Standard_Real aMax = -DBL_MAX; + Standard_Real aMin = DBL_MAX; + for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) + { + Standard_Real aProjection = theFrustum->myVertices[aVertIdx].XYZ().Ptr()[aDim]; + aMax = Max (aMax, aProjection); + aMin = Min (aMin, aProjection); + } + theFrustum->myMaxOrthoVertsProjections[aDim] = aMax; + theFrustum->myMinOrthoVertsProjections[aDim] = aMin; } } @@ -69,131 +97,71 @@ void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1, // V2_Far myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0); - computeFrustumNormals (myVertices, myPlanes); - - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx]; - for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) - { - Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - myMaxVertsProjections[aPlaneIdx] = aMax; - myMinVertsProjections[aPlaneIdx] = aMin; - } - - SelectMgr_Vec3 aDimensions[3] = - { - SelectMgr_Vec3 (1.0, 0.0, 0.0), - SelectMgr_Vec3 (0.0, 1.0, 0.0), - SelectMgr_Vec3 (0.0, 0.0, 1.0) - }; - - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) - { - Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - myMaxOrthoVertsProjections[aDim] = aMax; - myMinOrthoVertsProjections[aDim] = aMin; - } - // V0_Near - V0_Far - myEdgeDirs[0] = myVertices[0] - myVertices[3]; + myEdgeDirs[0] = myVertices[0].XYZ() - myVertices[3].XYZ(); // V1_Near - V1_Far - myEdgeDirs[1] = myVertices[1] - myVertices[4]; + myEdgeDirs[1] = myVertices[1].XYZ() - myVertices[4].XYZ(); // V2_Near - V1_Far - myEdgeDirs[2] = myVertices[2] - myVertices[5]; + myEdgeDirs[2] = myVertices[2].XYZ() - myVertices[5].XYZ(); // V1_Near - V0_Near - myEdgeDirs[3] = myVertices[1] - myVertices[0]; + myEdgeDirs[3] = myVertices[1].XYZ() - myVertices[0].XYZ(); // V2_Near - V1_Near - myEdgeDirs[4] = myVertices[2] - myVertices[1]; + myEdgeDirs[4] = myVertices[2].XYZ() - myVertices[1].XYZ(); // V1_Near - V0_Near - myEdgeDirs[5] = myVertices[2] - myVertices[0]; + myEdgeDirs[5] = myVertices[2].XYZ() - myVertices[0].XYZ(); + + computeFrustumNormals (myEdgeDirs, myPlanes); + + cacheVertexProjections (this); } //======================================================================= -// function : Transform -// purpose : Returns a copy of the frustum transformed according to the matrix given +// function : ScaleAndTransform +// purpose : 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. //======================================================================= -NCollection_Handle SelectMgr_TriangularFrustum::Transform (const gp_Trsf& theTrsf) +NCollection_Handle SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/, + const gp_Trsf& theTrsf) { SelectMgr_TriangularFrustum* aRes = new SelectMgr_TriangularFrustum(); // V0_Near - aRes->myVertices[0] = SelectMgr_MatOp::Transform (theTrsf, myVertices[0]); + aRes->myVertices[0] = myVertices[0].Transformed (theTrsf); // V1_Near - aRes->myVertices[1] = SelectMgr_MatOp::Transform (theTrsf, myVertices[1]); + aRes->myVertices[1] = myVertices[1].Transformed (theTrsf); // V2_Near - aRes->myVertices[2] = SelectMgr_MatOp::Transform (theTrsf, myVertices[2]); + aRes->myVertices[2] = myVertices[2].Transformed (theTrsf); // V0_Far - aRes->myVertices[3] = SelectMgr_MatOp::Transform (theTrsf, myVertices[3]); + aRes->myVertices[3] = myVertices[3].Transformed (theTrsf); // V1_Far - aRes->myVertices[4] = SelectMgr_MatOp::Transform (theTrsf, myVertices[4]); + aRes->myVertices[4] = myVertices[4].Transformed (theTrsf); // V2_Far - aRes->myVertices[5] = SelectMgr_MatOp::Transform (theTrsf, myVertices[5]); + aRes->myVertices[5] = myVertices[5].Transformed (theTrsf); aRes->myIsOrthographic = myIsOrthographic; - computeFrustumNormals (aRes->myVertices, aRes->myPlanes); - - for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx]; - for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) - { - Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - aRes->myMaxVertsProjections[aPlaneIdx] = aMax; - aRes->myMinVertsProjections[aPlaneIdx] = aMin; - } - - SelectMgr_Vec3 aDimensions[3] = - { - SelectMgr_Vec3 (1.0, 0.0, 0.0), - SelectMgr_Vec3 (0.0, 1.0, 0.0), - SelectMgr_Vec3 (0.0, 0.0, 1.0) - }; - - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMax = -DBL_MAX; - Standard_Real aMin = DBL_MAX; - for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) - { - Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]); - aMax = Max (aMax, aProjection); - aMin = Min (aMin, aProjection); - } - aRes->myMaxOrthoVertsProjections[aDim] = aMax; - aRes->myMinOrthoVertsProjections[aDim] = aMin; - } - // V0_Near - V0_Far - aRes->myEdgeDirs[0] = aRes->myVertices[0] - aRes->myVertices[3]; + aRes->myEdgeDirs[0] = aRes->myVertices[0].XYZ() - aRes->myVertices[3].XYZ(); // V1_Near - V1_Far - aRes->myEdgeDirs[1] = aRes->myVertices[1] - aRes->myVertices[4]; + aRes->myEdgeDirs[1] = aRes->myVertices[1].XYZ() - aRes->myVertices[4].XYZ(); // V2_Near - V1_Far - aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[5]; + aRes->myEdgeDirs[2] = aRes->myVertices[2].XYZ() - aRes->myVertices[5].XYZ(); // V1_Near - V0_Near - aRes->myEdgeDirs[3] = aRes->myVertices[1] - aRes->myVertices[0]; + aRes->myEdgeDirs[3] = aRes->myVertices[1].XYZ() - aRes->myVertices[0].XYZ(); // V2_Near - V1_Near - aRes->myEdgeDirs[4] = aRes->myVertices[2] - aRes->myVertices[1]; + aRes->myEdgeDirs[4] = aRes->myVertices[2].XYZ() - aRes->myVertices[1].XYZ(); // V1_Near - V0_Near - aRes->myEdgeDirs[5] = aRes->myVertices[2] - aRes->myVertices[0]; + aRes->myEdgeDirs[5] = aRes->myVertices[2].XYZ() - aRes->myVertices[0].XYZ(); + + computeFrustumNormals (aRes->myEdgeDirs, aRes->myPlanes); + + cacheVertexProjections (aRes); return NCollection_Handle (aRes); } @@ -203,10 +171,11 @@ NCollection_Handle SelectMgr_TriangularFrustum::Transform // purpose : SAT intersection test between defined volume and // given axis-aligned box //======================================================================= -Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const BVH_Box& theBox, +Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPt, + const SelectMgr_Vec3& theMaxPt, Standard_Real& /*theDepth*/) { - return hasOverlap (theBox.CornerMin(), theBox.CornerMax()); + return hasOverlap (theMinPt, theMaxPt); } // ======================================================================= @@ -261,7 +230,7 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const Handle(TColgp_HArr } else if (theSensType == Select3D_TOS_INTERIOR) { - SelectMgr_Vec3 aNorm (RealLast()); + gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast())); return hasOverlap (theArrayOfPnts, aNorm); } @@ -302,7 +271,7 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt1, } else if (theSensType == Select3D_TOS_INTERIOR) { - SelectMgr_Vec3 aNorm (RealLast()); + gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast())); return hasOverlap (thePnt1, thePnt2, thePnt3, aNorm); } diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx index a94fc7ec04..e9ced7eb67 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx @@ -40,12 +40,14 @@ public: const gp_Pnt2d& theP3) Standard_OVERRIDE; //! Returns a copy of the frustum transformed according to the matrix given - virtual NCollection_Handle Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE; + virtual NCollection_Handle ScaleAndTransform (const Standard_Integer theScale, + const gp_Trsf& theTrsf) Standard_OVERRIDE; // SAT Tests for different objects //! SAT intersection test between defined volume and given axis-aligned box - virtual Standard_Boolean Overlaps (const BVH_Box& theBox, + virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt, + const SelectMgr_Vec3& theMaxPnt, Standard_Real& theDepth) Standard_OVERRIDE; //! Returns true if selecting volume is overlapped by axis-aligned bounding box @@ -81,6 +83,10 @@ public: //! Nullifies the handle to corresponding builder instance to prevent memory leaks void Clear(); + +private: + + void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum); }; #endif // _SelectMgr_TriangularFrustum_HeaderFile diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx index 2ee203bfb4..dacf33badf 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx @@ -102,17 +102,24 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint } // ======================================================================= -// function : Transform -// purpose : Returns a copy of the frustum with all sub-volumes transformed -// according to the matrix given +// function : ScaleAndTransform +// purpose : 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. // ======================================================================= -NCollection_Handle SelectMgr_TriangularFrustumSet::Transform (const gp_Trsf& theTrsf) +NCollection_Handle SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale, + const gp_Trsf& theTrsf) { SelectMgr_TriangularFrustumSet* aRes = new SelectMgr_TriangularFrustumSet(); for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { - aRes->myFrustums.Append (NCollection_Handle::DownCast (anIter.Value()->Transform (theTrsf))); + aRes->myFrustums.Append (NCollection_Handle::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf))); } return NCollection_Handle (aRes); @@ -122,12 +129,13 @@ NCollection_Handle SelectMgr_TriangularFrustumSet::Transf // function : Overlaps // purpose : // ======================================================================= -Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const BVH_Box& theBox, +Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& theMinPnt, + const SelectMgr_Vec3& theMaxPnt, Standard_Real& theDepth) { for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { - if (anIter.Value()->Overlaps (theBox, theDepth)) + if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, theDepth)) return Standard_True; } diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx index 8003d4f140..6b7b97805c 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx @@ -48,29 +48,31 @@ public: virtual void Build (const TColgp_Array1OfPnt2d& thePoints) Standard_OVERRIDE; //! Returns a copy of the frustum with all sub-volumes transformed according to the matrix given - virtual NCollection_Handle Transform (const gp_Trsf& theTrsf) Standard_OVERRIDE; + virtual NCollection_Handle ScaleAndTransform (const Standard_Integer theScale, + const gp_Trsf& theTrsf) Standard_OVERRIDE; - virtual Standard_Boolean Overlaps (const BVH_Box& theBox, + virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt, + const SelectMgr_Vec3& theMaxPnt, Standard_Real& theDepth) Standard_OVERRIDE; virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt, const SelectMgr_Vec3& theMaxPnt, Standard_Boolean* theInside) Standard_OVERRIDE; - virtual Standard_Boolean Overlaps (const gp_Pnt& thePt, + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth) Standard_OVERRIDE; - virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts, + virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) Standard_OVERRIDE; - virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, - const gp_Pnt& thePt2, + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, Standard_Real& theDepth) Standard_OVERRIDE; - virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, - const gp_Pnt& thePt2, - const gp_Pnt& thePt3, + virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + const gp_Pnt& thePnt3, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) Standard_OVERRIDE; diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 8a5190f7f7..2675b45332 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -45,8 +45,8 @@ IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, MMgt_TShared) //======================================================================= SelectMgr_ToleranceMap::SelectMgr_ToleranceMap() { - myLargestKey = -1.0; - myCustomTolerance = -1.0; + myLargestKey = 2; + myCustomTolerance = -1; } //======================================================================= @@ -63,7 +63,7 @@ SelectMgr_ToleranceMap::~SelectMgr_ToleranceMap() // purpose : Adds the value given to map, checks if the current tolerance value // should be replaced by theTolerance //======================================================================= -void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance) +void SelectMgr_ToleranceMap::Add (const Standard_Integer& theTolerance) { if (myTolerances.IsBound (theTolerance)) { @@ -92,7 +92,7 @@ void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance) // purpose : Decrements a counter of the tolerance given, checks if the current tolerance value // should be recalculated //======================================================================= -void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance) +void SelectMgr_ToleranceMap::Decrement (const Standard_Integer& theTolerance) { if (myTolerances.IsBound (theTolerance)) { @@ -101,8 +101,8 @@ void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance) if (Abs (theTolerance - myLargestKey) < Precision::Confusion() && aFreq == 0) { - myLargestKey = 0.0; - for (NCollection_DataMap::Iterator anIter (myTolerances); anIter.More(); anIter.Next()) + myLargestKey = 0; + for (NCollection_DataMap::Iterator anIter (myTolerances); anIter.More(); anIter.Next()) { if (anIter.Value() != 0) myLargestKey = Max (myLargestKey, anIter.Key()); @@ -115,16 +115,16 @@ void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance) // function: Tolerance // purpose : Returns a current tolerance that must be applied //======================================================================= -Standard_Real SelectMgr_ToleranceMap::Tolerance() +Standard_Integer SelectMgr_ToleranceMap::Tolerance() const { - return myCustomTolerance < 0.0 ? myLargestKey : myCustomTolerance; + return myCustomTolerance < 0 ? myLargestKey : myCustomTolerance; } //======================================================================= // function: SetCustomTolerance // purpose : Sets tolerance to the given one and disables adaptive checks //======================================================================= -void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theTolerance) +void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Integer theTolerance) { myCustomTolerance = theTolerance; } @@ -135,7 +135,7 @@ void SelectMgr_ToleranceMap::SetCustomTolerance (const Standard_Real theToleranc //======================================================================= void SelectMgr_ToleranceMap::ResetDefaults() { - myCustomTolerance = -1.0; + myCustomTolerance = -1; } //================================================== @@ -144,7 +144,6 @@ void SelectMgr_ToleranceMap::ResetDefaults() //================================================== SelectMgr_ViewerSelector::SelectMgr_ViewerSelector(): preferclosest(Standard_True), -mytolerance(2.0), myToUpdateTolerance (Standard_True), myCurRank (0), myIsLeftChildQueuedFirst (Standard_False), @@ -168,7 +167,6 @@ void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theS theSelection->SetSelectionState (SelectMgr_SOS_Activated); myTolerances.Add (theSelection->Sensitivity()); - mytolerance = myTolerances.Tolerance(); myToUpdateTolerance = Standard_True; } @@ -187,7 +185,6 @@ void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& th theSelection->SetSelectionState (SelectMgr_SOS_Deactivated); myTolerances.Decrement (theSelection->Sensitivity()); - mytolerance = myTolerances.Tolerance(); myToUpdateTolerance = Standard_True; } @@ -211,29 +208,6 @@ Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select && theEntity->SensitivityFactor() < myTolerances.Tolerance(); } -//======================================================================= -// function: scaleAndTransform -// purpose : Applies given scale and transformation matrices to the default selecting volume manager -//======================================================================= -SelectMgr_SelectingVolumeManager SelectMgr_ViewerSelector::scaleAndTransform (const Standard_Real theScale, - const gp_Trsf& theTrsf) -{ - SelectMgr_SelectingVolumeManager aMgr; - - if (theScale > Precision::Angular()) - { - aMgr = mySelectingVolumeMgr.Scale (theScale); - } - - if (theTrsf.Form() != gp_Identity) - { - aMgr = aMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Unknown ? - mySelectingVolumeMgr.Transform (theTrsf) : aMgr.Transform (theTrsf); - } - - return aMgr; -} - //======================================================================= // function: checkOverlap // purpose : Internal function that checks if a particular sensitive @@ -261,7 +235,7 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive Standard_Integer aPriority = anOwner->Priority(); - SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33, preferclosest); + SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33.0, preferclosest); if (mystored.Contains (anOwner)) { if (theMgr.GetActiveSelectionType() != 1) @@ -283,6 +257,40 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive } } +//======================================================================= +// function: computeFrustum +// purpose : Internal function that checks if a current selecting frustum +// needs to be scaled and transformed for the entity and performs +// necessary calculations +//======================================================================= +void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt, + const gp_Trsf& theInvTrsf, + SelectMgr_FrustumCache& theCachedMgrs, + SelectMgr_SelectingVolumeManager& theResMgr) +{ + Standard_Integer aScale = 1; + const Standard_Boolean toScale = isToScaleFrustum (theEnt); + if (toScale) + { + aScale = theEnt->SensitivityFactor(); + } + if (theEnt->HasInitLocation()) + { + theResMgr = + mySelectingVolumeMgr.ScaleAndTransform (aScale, theEnt->InvInitLocation() * theInvTrsf); + } + else if (toScale) + { + if (!theCachedMgrs.IsBound (aScale)) + { + theCachedMgrs.Bind (aScale, + mySelectingVolumeMgr.ScaleAndTransform(aScale, theInvTrsf)); + } + + theResMgr = theCachedMgrs.Find (aScale); + } +} + //======================================================================= // function: traverseObject // purpose : Internal function that checks if there is possible overlap @@ -300,9 +308,9 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable const NCollection_Handle >& aSensitivesTree = anEntitySet->BVH(); SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ? - mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr; + mySelectingVolumeMgr.ScaleAndTransform (1, theObject->InversedTransformation()) : mySelectingVolumeMgr; - NCollection_DataMap aScaledTrnsfFrustums; + SelectMgr_FrustumCache aScaledTrnsfFrustums; Standard_Integer aNode = 0; // a root node if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0), @@ -357,16 +365,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable { const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive(); SelectMgr_SelectingVolumeManager aTmpMgr = aMgr; - if (isToScaleFrustum (anEnt)) - { - if (!aScaledTrnsfFrustums.IsBound (anEnt->DynamicType())) - { - aScaledTrnsfFrustums.Bind (anEnt->DynamicType(), - scaleAndTransform (anEnt->SensitivityFactor(), theObject->InversedTransformation())); - } - - aTmpMgr = aScaledTrnsfFrustums.Find (anEnt->DynamicType()); - } + computeFrustum (anEnt, theObject->InversedTransformation(), aScaledTrnsfFrustums, aTmpMgr); checkOverlap (anEnt, anIdx, aTmpMgr); } } diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx index 0d95e77fd3..f4b865657c 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx @@ -57,6 +57,8 @@ typedef NCollection_DataMap SelectMgr_MapOfOwnerDetectedEntities; typedef NCollection_DataMap::Iterator SelectMgr_MapOfOwnerDetectedEntitiesIterator; +typedef NCollection_DataMap SelectMgr_FrustumCache; + //! An internal class for calculation of current largest tolerance value which will be applied //! for creation of selecting frustum by default. Each time the selection set is deactivated, //! maximum tolerance value will be recalculated. If a user enables custom precision using @@ -73,25 +75,25 @@ public: //! Adds the value given to map, checks if the current tolerance value //! should be replaced by theTolerance - Standard_EXPORT void Add (const Standard_Real& theTolerance); + Standard_EXPORT void Add (const Standard_Integer& theTolerance); //! Decrements a counter of the tolerance given, checks if the current tolerance value //! should be recalculated - Standard_EXPORT void Decrement (const Standard_Real& theTolerance); + Standard_EXPORT void Decrement (const Standard_Integer& theTolerance); //! Returns a current tolerance that must be applied - Standard_EXPORT Standard_Real Tolerance(); + Standard_EXPORT Standard_Integer Tolerance() const; //! Sets tolerance to the given one and disables adaptive checks - Standard_EXPORT void SetCustomTolerance (const Standard_Real theTolerance); + Standard_EXPORT void SetCustomTolerance (const Standard_Integer theTolerance); //! Unsets a custom tolerance and enables adaptive checks Standard_EXPORT void ResetDefaults(); private: - NCollection_DataMap myTolerances; - Standard_Real myLargestKey; - Standard_Real myCustomTolerance; + NCollection_DataMap myTolerances; + Standard_Integer myLargestKey; + Standard_Integer myCustomTolerance; }; //! A framework to define finding, sorting the sensitive @@ -132,7 +134,7 @@ public: Standard_EXPORT void Clear(); //! returns the Sensitivity of picking - Standard_Real Sensitivity() const; + Standard_Integer Sensitivity() const; //! Sorts the detected entites by priority and distance. //! to be redefined if other criterion are used... @@ -283,10 +285,6 @@ protected: //! Checks if the entity given requires to scale current selecting frustum Standard_Boolean isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity); - //! Applies given scale and transformation matrices to the default selecting volume manager - SelectMgr_SelectingVolumeManager scaleAndTransform (const Standard_Real theScale, - const gp_Trsf& theTrsf); - private: void Activate (const Handle(SelectMgr_Selection)& theSelection); @@ -296,10 +294,17 @@ private: //! removes a Selection from the Selector void Remove (const Handle(SelectMgr_Selection)& aSelection); + //! Internal function that checks if a current selecting frustum + //! needs to be scaled and transformed for the entity and performs + //! necessary calculations + void computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt, + const gp_Trsf& theInvTrsf, + SelectMgr_FrustumCache& theCachedMgrs, + SelectMgr_SelectingVolumeManager& theResMgr); + protected: Standard_Boolean preferclosest; - Standard_Real mytolerance; Standard_Boolean myToUpdateTolerance; SelectMgr_IndexedDataMapOfOwnerCriterion mystored; SelectMgr_SelectingVolumeManager mySelectingVolumeMgr; diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.lxx b/src/SelectMgr/SelectMgr_ViewerSelector.lxx index 3f9c99183a..70c4ab04de 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.lxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.lxx @@ -12,9 +12,9 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -inline Standard_Real SelectMgr_ViewerSelector::Sensitivity() const +inline Standard_Integer SelectMgr_ViewerSelector::Sensitivity() const { - return mytolerance; + return myTolerances.Tolerance(); } inline void SelectMgr_ViewerSelector::Init() diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.cxx b/src/StdSelect/StdSelect_ViewerSelector3d.cxx index 3c0967bb07..0862b34903 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.cxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.cxx @@ -93,15 +93,14 @@ StdSelect_ViewerSelector3d::StdSelect_ViewerSelector3d() {} // Function: SetPixelTolerance // Purpose : //======================================================================= -void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Real theTolerance) +void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Integer theTolerance) { - if (mytolerance != theTolerance) + if (myTolerances.Tolerance() != theTolerance) { - if (theTolerance < 0.0) + if (theTolerance < 0) myTolerances.ResetDefaults(); else myTolerances.SetCustomTolerance (theTolerance); - mytolerance = myTolerances.Tolerance(); myToUpdateTolerance = Standard_True; } } @@ -118,7 +117,7 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix, if(myToUpdateTolerance) { - mySelectingVolumeMgr.SetPixelTolerance (mytolerance); + mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance()); myToUpdateTolerance = Standard_False; } diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.hxx b/src/StdSelect/StdSelect_ViewerSelector3d.hxx index 86407bcfd5..1970cd9c42 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.hxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.hxx @@ -48,10 +48,10 @@ public: Standard_EXPORT StdSelect_ViewerSelector3d(); //! Sets the pixel tolerance . - Standard_EXPORT void SetPixelTolerance (const Standard_Real theTolerance); + Standard_EXPORT void SetPixelTolerance (const Standard_Integer theTolerance); //! Returns the pixel tolerance. - Standard_Real PixelTolerance() const; + inline Standard_Integer PixelTolerance() const; //! Picks the sensitive entity at the pixel coordinates of //! the mouse and . The selector looks for touched areas and owners. diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.lxx b/src/StdSelect/StdSelect_ViewerSelector3d.lxx index c29b733070..6f941d9353 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.lxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.lxx @@ -12,7 +12,7 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -inline Standard_Real StdSelect_ViewerSelector3d::PixelTolerance() const +inline Standard_Integer StdSelect_ViewerSelector3d::PixelTolerance() const { - return mytolerance; + return myTolerances.Tolerance(); } diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index dc78b59bd2..36b0fcb5d7 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -768,11 +768,11 @@ static int VSelPrecision(Draw_Interpretor& di, Standard_Integer argc, const char anArg.LowerCase(); if (anArg == "-unset") { - aContext->SetPixelTolerance (-1.0); + aContext->SetPixelTolerance (-1); } else { - aContext->SetPixelTolerance (anArg.RealValue()); + aContext->SetPixelTolerance (anArg.IntegerValue()); } } @@ -4278,11 +4278,12 @@ static Standard_Integer VState (Draw_Interpretor& theDI, const Handle(SelectBasics_SensitiveEntity)& anEntity = aSelector->DetectedEntity(); Handle(SelectMgr_EntityOwner) anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId()); Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable()); - SelectMgr_SelectingVolumeManager aMgr = anObj->HasTransformation() ? aSelector->GetManager().Transform (anObj->InversedTransformation()) - : aSelector->GetManager(); + SelectMgr_SelectingVolumeManager aMgr = + anObj->HasTransformation() ? aSelector->GetManager().ScaleAndTransform (1, anObj->InversedTransformation()) + : aSelector->GetManager(); SelectBasics_PickResult aResult; anEntity->Matches (aMgr, aResult); - NCollection_Vec3 aDetectedPnt = aMgr.DetectedPoint (aResult.Depth()); + gp_Pnt aDetectedPnt = aMgr.DetectedPoint (aResult.Depth()); TCollection_AsciiString aName = GetMapOfAIS().Find1 (anObj); aName.LeftJustify (20, ' '); @@ -4291,7 +4292,7 @@ static Standard_Integer VState (Draw_Interpretor& theDI, " Depth: %+.3f Distance: %+.3f Point: %+.3f %+.3f %+.3f", aResult.Depth(), aResult.DistToGeomCenter(), - aDetectedPnt.x(), aDetectedPnt.y(), aDetectedPnt.z()); + aDetectedPnt.X(), aDetectedPnt.Y(), aDetectedPnt.Z()); theDI << " " << aName << anInfoStr << " (" << anEntity->DynamicType()->Name() << ")" diff --git a/src/gp/gp_XYZ.cdl b/src/gp/gp_XYZ.cdl index a775fdb70a..6251d4665f 100644 --- a/src/gp/gp_XYZ.cdl +++ b/src/gp/gp_XYZ.cdl @@ -101,6 +101,17 @@ is ---C++: inline ---Purpose: Returns the Z coordinate + Ptr (me) returns Real + --- Purpose : Returns a const ptr to coordinates location. + -- Is useful for algorithms, but DOES NOT PERFORM ANY CHECKS! + ---C++: return const * + is static; + + Ptr (me : in out) returns Real; + --- Purpose : Returns a ptr to coordinates location. + -- Is useful for algorithms, but DOES NOT PERFORM ANY CHECKS! + ---C++: return * + Modulus (me) returns Real is static; --- Purpose : computes Sqrt (X*X + Y*Y + Z*Z) where X, Y and Z are the three coordinates of this XYZ object. ---C++: inline diff --git a/src/gp/gp_XYZ.lxx b/src/gp/gp_XYZ.lxx index 9a9ed2a754..144e3b531d 100644 --- a/src/gp/gp_XYZ.lxx +++ b/src/gp/gp_XYZ.lxx @@ -304,8 +304,6 @@ inline gp_XYZ operator* (const Standard_Real Scalar, const gp_XYZ& Coord1) { return Coord1.Multiplied (Scalar); } +inline const Standard_Real* gp_XYZ::Ptr() const { return (&x); } - - - - +inline Standard_Real* gp_XYZ::Ptr() { return (&x); }