1 // Created on: 2014-05-22
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 #include <SelectMgr_BaseFrustum.hxx>
17 
18 #include <Message.hxx>
19 #include <SelectMgr_FrustumBuilder.hxx>
20 #include <Standard_Dump.hxx>
21 
IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,SelectMgr_BaseIntersector)22 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BaseFrustum, SelectMgr_BaseIntersector)
23 
24 //=======================================================================
25 // function : SelectMgr_BaseFrustum
26 // purpose  :
27 //=======================================================================
28 SelectMgr_BaseFrustum::SelectMgr_BaseFrustum()
29 : myPixelTolerance (2)
30 {
31   myBuilder = new SelectMgr_FrustumBuilder();
32 }
33 
34 //=======================================================================
35 // function : SetCamera
36 // purpose  :
37 //=======================================================================
SetCamera(const Handle (Graphic3d_Camera)& theCamera)38 void SelectMgr_BaseFrustum::SetCamera (const Handle(Graphic3d_Camera)& theCamera)
39 {
40   SelectMgr_BaseIntersector::SetCamera (theCamera);
41   if (!myBuilder.IsNull())
42   {
43     myBuilder->SetCamera (theCamera);
44     myBuilder->InvalidateViewport();
45   }
46 }
47 
48 //=======================================================================
49 // function : SetViewport
50 // purpose  : Passes viewport parameters to builder
51 //=======================================================================
SetViewport(const Standard_Real theX,const Standard_Real theY,const Standard_Real theWidth,const Standard_Real theHeight)52 void SelectMgr_BaseFrustum::SetViewport (const Standard_Real theX,
53                                          const Standard_Real theY,
54                                          const Standard_Real theWidth,
55                                          const Standard_Real theHeight)
56 {
57   myBuilder->SetViewport (theX, theY, theWidth, theHeight);
58 }
59 
60 //=======================================================================
61 // function : SetPixelTolerance
62 // purpose  :
63 //=======================================================================
SetPixelTolerance(const Standard_Integer theTol)64 void SelectMgr_BaseFrustum::SetPixelTolerance (const Standard_Integer theTol)
65 {
66   myPixelTolerance = theTol;
67 }
68 
69 //=======================================================================
70 // function : SetWindowSize
71 // purpose  :
72 //=======================================================================
SetWindowSize(const Standard_Integer theWidth,const Standard_Integer theHeight)73 void SelectMgr_BaseFrustum::SetWindowSize (const Standard_Integer theWidth, const Standard_Integer theHeight)
74 {
75   myBuilder->SetWindowSize (theWidth, theHeight);
76 }
77 
78 //=======================================================================
79 // function : WindowSize
80 // purpose  :
81 //=======================================================================
WindowSize(Standard_Integer & theWidth,Standard_Integer & theHeight) const82 void SelectMgr_BaseFrustum::WindowSize (Standard_Integer& theWidth,
83                                         Standard_Integer& theHeight) const
84 {
85   myBuilder->WindowSize (theWidth, theHeight);
86 }
87 
88 //=======================================================================
89 // function : SetBuilder
90 // purpose  :
91 //=======================================================================
SetBuilder(const Handle (SelectMgr_FrustumBuilder)& theBuilder)92 void SelectMgr_BaseFrustum::SetBuilder (const Handle(SelectMgr_FrustumBuilder)& theBuilder)
93 {
94   myBuilder.Nullify();
95   myBuilder = theBuilder;
96   if (!myBuilder.IsNull())
97   {
98     myCamera = myBuilder->Camera();
99   }
100 }
101 
102 //=======================================================================
103 // function : IsBoundariesIntersectSphere
104 // purpose  :
105 //=======================================================================
IsBoundaryIntersectSphere(const gp_Pnt & theCenter,const Standard_Real theRadius,const gp_Dir & thePlaneNormal,const TColgp_Array1OfPnt & theBoundaries,Standard_Boolean & theBoundaryInside) const106 Standard_Boolean SelectMgr_BaseFrustum::IsBoundaryIntersectSphere (const gp_Pnt& theCenter,
107                                                                    const Standard_Real theRadius,
108                                                                    const gp_Dir& thePlaneNormal,
109                                                                    const TColgp_Array1OfPnt& theBoundaries,
110                                                                    Standard_Boolean& theBoundaryInside) const
111 {
112   for (Standard_Integer anIdx = theBoundaries.Lower(); anIdx < theBoundaries.Upper(); ++anIdx)
113   {
114     const Standard_Integer aNextIdx = ((anIdx + 1) == theBoundaries.Upper()) ? theBoundaries.Lower() : (anIdx + 1);
115     const gp_Pnt aPnt1 = theBoundaries.Value (anIdx);
116     const gp_Pnt aPnt2 = theBoundaries.Value (aNextIdx);
117     if (aPnt1.Distance (aPnt2) < Precision::Confusion())
118     {
119       continue;
120     }
121 
122     // Projections of the points on the plane
123     const gp_Pnt aPntProj1 = aPnt1.XYZ() - thePlaneNormal.XYZ() * aPnt1.XYZ().Dot (thePlaneNormal.XYZ());
124     const gp_Pnt aPntProj2 = aPnt2.XYZ() - thePlaneNormal.XYZ() * aPnt2.XYZ().Dot (thePlaneNormal.XYZ());
125     if (aPntProj1.Distance (theCenter) < theRadius || aPntProj2.Distance (theCenter) < theRadius) // polygon intersects the sphere
126     {
127       theBoundaryInside = Standard_True;
128       return Standard_True;
129     }
130 
131     gp_Dir aRayDir (gp_Vec (aPntProj1, aPntProj2));
132     Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
133     if (RaySphereIntersection (theCenter, theRadius, aPntProj1, aRayDir, aTimeEnter, aTimeLeave))
134     {
135       if ((aTimeEnter > 0 && aTimeEnter < aPntProj1.Distance (aPntProj2))
136        || (aTimeLeave > 0 && aTimeLeave < aPntProj1.Distance (aPntProj2)))
137       {
138         return Standard_True; // polygon crosses  the sphere
139       }
140     }
141   }
142   return Standard_False;
143 }
144 
145 //=======================================================================
146 //function : DumpJson
147 //purpose  :
148 //=======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const149 void SelectMgr_BaseFrustum::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
150 {
151   OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_BaseFrustum)
152   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, SelectMgr_BaseIntersector)
153 
154   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPixelTolerance)
155   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myBuilder)
156 }
157