#include <gp_Dir.hxx>
#include <gp_Ax3.hxx>
#include <gp_GTrsf.hxx>
+#include <gp_Pln.hxx>
#include <V3d_PerspectiveView.hxx>
-#include <V3d_Plane.hxx>
#include <Select3D_SensitiveEntity.hxx>
#include <Graphic3d_ArrayOfPolylines.hxx>
+#include <Graphic3d_SetOfHClipPlane.hxx>
+#include <SelectMgr_SelectableObject.hxx>
#include <SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive.hxx>
#include <SelectBasics_ListOfBox2d.hxx>
#include <Visual3d_TransientManager.hxx>
const Standard_Integer YPix,
const Handle(V3d_View)& aView)
{
+ SetClipping (aView->GetClipPlanes());
UpdateProj(aView);
Standard_Real Xr3d,Yr3d,Zr3d;
gp_Pnt2d P2d;
aView->Convert(XPix,YPix,Xr3d,Yr3d,Zr3d);
myprj->Project(gp_Pnt(Xr3d,Yr3d,Zr3d),P2d);
- // compute depth limits if clipping plane(s) enabled
- gp_Lin anEyeLine = myprj->Shoot (P2d.X(), P2d.Y());
- Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
- Standard_Real aDepthFrom = ShortRealFirst();
- Standard_Real aDepthTo = ShortRealLast();
- for (aView->InitActivePlanes(); aView->MoreActivePlanes(); aView->NextActivePlanes())
- {
- aView->ActivePlane()->Plane (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
- const gp_Dir& anEyeLineDir = anEyeLine.Direction();
- gp_Dir aPlaneNormal (aPlaneA, aPlaneB, aPlaneC);
-
- Standard_Real aDotProduct = anEyeLineDir.Dot (aPlaneNormal);
- Standard_Real aDirection = -(aPlaneD + anEyeLine.Location().XYZ().Dot (aPlaneNormal.XYZ()));
- if (Abs (aDotProduct) < Precision::Angular())
- {
- // eyeline parallel to the clipping plane
- if (aDirection > 0.0)
- {
- // invalidate the interval
- aDepthTo = ShortRealFirst();
- aDepthFrom = ShortRealFirst();
- break;
- }
- // just ignore this plane
- continue;
- }
-
- // compute distance along the eyeline from eyeline location to intersection with clipping plane
- Standard_Real aDepth = aDirection / aDotProduct;
-
- // reduce depth limits
- if (aDotProduct < 0.0)
- {
- if (aDepth < aDepthTo)
- {
- aDepthTo = aDepth;
- }
- }
- else if (aDepth > aDepthFrom)
- {
- aDepthFrom = aDepth;
- }
- }
- myprj->DepthMinMax (aDepthFrom, aDepthTo);
-
InitSelect(P2d.X(),P2d.Y());
}
}
//=======================================================================
-//function : ReactivateProjector
+//function : SetClipping
//purpose :
//=======================================================================
-void StdSelect_ViewerSelector3d::ReactivateProjector()
+void StdSelect_ViewerSelector3d::SetClipping (const Graphic3d_SetOfHClipPlane& thePlanes)
{
- Handle(SelectBasics_SensitiveEntity) BS;
- for (SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive it (myentities); it.More(); it.Next())
+ myClipPlanes = thePlanes;
+}
+
+//=======================================================================
+//function : ComputeClipRange
+//purpose :
+//=======================================================================
+void StdSelect_ViewerSelector3d::ComputeClipRange (const Graphic3d_SetOfHClipPlane& thePlanes,
+ const gp_Lin& thePickLine,
+ Standard_Real& theDepthMin,
+ Standard_Real& theDepthMax) const
+{
+ theDepthMin = RealFirst();
+ theDepthMax = RealLast();
+ Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
+
+ Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes);
+ for (; aPlaneIt.More(); aPlaneIt.Next())
{
- BS = it.Value();
- if (BS->Is3D())
+ const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value();
+ if (!aClipPlane->IsOn())
+ continue;
+
+ gp_Pln aGeomPlane = aClipPlane->ToPlane();
+
+ aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
+
+ const gp_Dir& aPlaneDir = aGeomPlane.Axis().Direction();
+ const gp_Dir& aPickDir = thePickLine.Direction();
+ const gp_XYZ& aPntOnLine = thePickLine.Location().XYZ();
+ const gp_XYZ& aPlaneDirXYZ = aPlaneDir.XYZ();
+
+ Standard_Real aDotProduct = aPickDir.Dot (aPlaneDir);
+ Standard_Real aDistance = -(aPntOnLine.Dot (aPlaneDirXYZ) + aPlaneD);
+
+ // check whether the pick line is parallel to clip plane
+ if (Abs (aDotProduct) < Precision::Angular())
{
- (*((Handle(Select3D_SensitiveEntity)*) &BS))->SetLastPrj (myprj);
+ if (aDistance > 0.0)
+ {
+ // line lies above the plane, thus no selection is possible
+ theDepthMin = 0.0;
+ theDepthMax = 0.0;
+ return;
+ }
+
+ // line lies below the plane and is not clipped, skip
+ continue;
+ }
+
+ // compute distance to point of pick line intersection with the plane
+ Standard_Real aIntDist = aDistance / aDotProduct;
+
+ // change depth limits for case of opposite and directed planes
+ if (aDotProduct < 0.0)
+ {
+ theDepthMax = Min (aIntDist, theDepthMax);
+ }
+ else if (aIntDist > theDepthMin)
+ {
+ theDepthMin = Max (aIntDist, theDepthMin);
}
}
}
+
+//=======================================================================
+//function : PickingLine
+//purpose :
+//=======================================================================
+gp_Lin StdSelect_ViewerSelector3d::PickingLine(const Standard_Real theX, const Standard_Real theY) const
+{
+ return myprj->Shoot (theX, theY);
+}
+
+//=======================================================================
+//function : DepthClipping
+//purpose :
+//=======================================================================
+void StdSelect_ViewerSelector3d::DepthClipping (const Standard_Real theX,
+ const Standard_Real theY,
+ Standard_Real& theDepthMin,
+ Standard_Real& theDepthMax) const
+{
+ return ComputeClipRange (myClipPlanes, PickingLine (theX, theY), theDepthMin, theDepthMax);
+}
+
+//=======================================================================
+//function : DepthClipping
+//purpose :
+//=======================================================================
+void StdSelect_ViewerSelector3d::DepthClipping (const Standard_Real theX,
+ const Standard_Real theY,
+ const Handle(SelectMgr_EntityOwner)& theOwner,
+ Standard_Real& theDepthMin,
+ Standard_Real& theDepthMax) const
+{
+ return ComputeClipRange (theOwner->Selectable()->GetClipPlanes(),
+ PickingLine (theX, theY),
+ theDepthMin, theDepthMax);
+}
+
+//=======================================================================
+//function : HasDepthClipping
+//purpose :
+//=======================================================================
+Standard_Boolean StdSelect_ViewerSelector3d::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const
+{
+ if (!theOwner->HasSelectable())
+ {
+ return Standard_False;
+ }
+
+ const Handle(SelectMgr_SelectableObject)& aSelectable = theOwner->Selectable();
+ return (aSelectable->GetClipPlanes().Size() > 0);
+}