0024070: OpenGL capped object-level clipping planes
[occt.git] / src / Select3D / Select3D_SensitiveFace.cxx
1 // Created on: 1995-03-27
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21 //Modif on jun-24-97 : introduction de CSLib_Class2d de LBR
22 //                     pour teste si on est dedans ou dehors...
23 //Modif on jul-21-97 : changement en harray1 pour eventuelles connexions ...
24
25 #include <Select3D_SensitiveFace.ixx>
26 #include <Select3D_Projector.hxx>
27 #include <SelectBasics_BasicTool.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <gp_Pnt.hxx>
30 #include <Precision.hxx>
31 #include <ElCLib.hxx>
32
33 #include <CSLib_Class2d.hxx>
34
35 //==================================================
36 // Function: Hide this constructor to the next version...
37 // Purpose : simply avoid interfering with the version update
38 //==================================================
39
40 Select3D_SensitiveFace::
41 Select3D_SensitiveFace(const Handle(SelectBasics_EntityOwner)& OwnerId,
42                        const TColgp_Array1OfPnt& ThePoints,
43                        const Select3D_TypeOfSensitivity aType):
44 Select3D_SensitivePoly(OwnerId, ThePoints),
45 mytype (aType)
46 {
47 }
48
49 //==================================================
50 // Function: Creation
51 // Purpose :
52 //==================================================
53
54 Select3D_SensitiveFace::
55 Select3D_SensitiveFace(const Handle(SelectBasics_EntityOwner)& OwnerId,
56                        const Handle(TColgp_HArray1OfPnt)& ThePoints,
57                        const Select3D_TypeOfSensitivity aType):
58 Select3D_SensitivePoly(OwnerId, ThePoints),
59 mytype (aType)
60 {
61 }
62
63 //==================================================
64 // Function: Matches
65 // Purpose :
66 //==================================================
67
68 Standard_Boolean Select3D_SensitiveFace::Matches (const SelectBasics_PickArgs& thePickArgs,
69                                                   Standard_Real& theMatchDMin,
70                                                   Standard_Real& theMatchDepth)
71 {
72   Standard_Real DMin2 = 0.;
73   Standard_Real Xmin = 0.,Ymin = 0.,Xmax = 0.,Ymax = 0.;
74   if(!Bnd_Box2d(mybox2d).IsVoid())
75   {
76     Bnd_Box2d(mybox2d).Get(Xmin,Ymin,Xmax,Ymax);
77     DMin2 = gp_XY(Xmax-Xmin,Ymax-Ymin).SquareModulus();
78   }
79   // calculation of a criterion of minimum distance...
80   // from start Dmin = size of the bounding box 2D,
81   // then min. distance of the polyhedron or cdg...
82
83   Standard_Real aTol2 = thePickArgs.Tolerance() * thePickArgs.Tolerance();
84   Standard_Integer aSize = mypolyg.Size(), anIndex;
85   gp_XY CDG;
86   for(anIndex=0;anIndex<aSize;++anIndex)
87   {
88     CDG+=mypolyg.Pnt2d(anIndex);
89   }
90
91   if(aSize>1)
92   {
93     CDG/=(aSize-1);
94   }
95   DMin2 = Min (DMin2, gp_XY (CDG.X() - thePickArgs.X(), CDG.Y() - thePickArgs.Y()).SquareModulus());
96   theMatchDMin = Sqrt(DMin2);
97
98   Standard_Boolean isplane2d(Standard_True);
99
100   for(anIndex=1;anIndex<aSize;++anIndex)
101   {
102     gp_XY V1(mypolyg.Pnt2d(anIndex)),V(thePickArgs.X(), thePickArgs.Y());
103     V1-=mypolyg.Pnt2d(anIndex-1);
104     V-=mypolyg.Pnt2d(anIndex-1);
105     Standard_Real Vector = V1^V;
106     Standard_Real V1V1 = V1.SquareModulus();
107     DMin2 =
108       (V1V1 <=aTol2) ?
109     Min(DMin2,V.SquareModulus()): // if the segment is too small...
110       Min(DMin2,Vector*Vector/V1V1);
111     //cdg ...
112     gp_XY PlaneTest(CDG);
113     PlaneTest-=mypolyg.Pnt2d(anIndex-1);
114     Standard_Real valtst = PlaneTest^V1;
115     if(isplane2d && Abs(valtst) > thePickArgs.Tolerance()) isplane2d=Standard_False;
116   }
117   if (isplane2d)
118   {
119     theMatchDepth = ComputeDepth (thePickArgs.PickLine(),
120                                   thePickArgs.DepthMin(),
121                                   thePickArgs.DepthMax());
122
123     return !thePickArgs.IsClipped (theMatchDepth);
124   }
125
126   //otherwise it is checked if the point is in the face...
127   TColgp_Array1OfPnt2d aArrayOf2dPnt(1, aSize);
128   Points2D(aArrayOf2dPnt);
129   CSLib_Class2d TheInOutTool (aArrayOf2dPnt,
130                               thePickArgs.Tolerance(),
131                               thePickArgs.Tolerance(),
132                               Xmin, Ymin, Xmax, Ymax);
133   Standard_Integer TheStat = TheInOutTool.SiDans (gp_Pnt2d (thePickArgs.X(), thePickArgs.Y()));
134
135   Standard_Boolean res(Standard_False);
136   switch(TheStat)
137   {
138   case 0:
139     res = Standard_True;
140   case 1:
141     {
142       if(mytype!=Select3D_TOS_BOUNDARY)
143         res = Standard_True;
144     }
145   }
146   if (res)
147   {
148     theMatchDepth = ComputeDepth (thePickArgs.PickLine(),
149                                   thePickArgs.DepthMin(),
150                                   thePickArgs.DepthMax());
151
152     return !thePickArgs.IsClipped (theMatchDepth);
153   }
154   return Standard_False;
155 }
156
157 //=======================================================================
158 //function : Matches
159 //purpose  :
160 //=======================================================================
161
162 Standard_Boolean Select3D_SensitiveFace::
163 Matches (const Standard_Real XMin,
164          const Standard_Real YMin,
165          const Standard_Real XMax,
166          const Standard_Real YMax,
167          const Standard_Real aTol)
168 {
169   Bnd_Box2d BoundBox;
170   BoundBox.Update(XMin-aTol,YMin-aTol,XMax+aTol,YMax+aTol);
171
172   for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
173   {
174     if(BoundBox.IsOut(mypolyg.Pnt2d(anIndex)))
175       return Standard_False;
176   }
177   return Standard_True;
178 }
179
180 //=======================================================================
181 //function : Matches
182 //purpose  :
183 //=======================================================================
184
185 Standard_Boolean Select3D_SensitiveFace::
186 Matches (const TColgp_Array1OfPnt2d& aPoly,
187          const Bnd_Box2d& aBox,
188          const Standard_Real aTol)
189 {
190   Standard_Real Umin,Vmin,Umax,Vmax;
191   aBox.Get(Umin,Vmin,Umax,Vmax);
192   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
193
194   gp_Pnt2d aPnt2d;
195   for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
196   {
197     Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
198     if(RES!=1)
199       return Standard_False;
200   }
201   return Standard_True;
202 }
203
204 //=======================================================================
205 //function : Dump
206 //purpose  :
207 //=======================================================================
208
209 void Select3D_SensitiveFace::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
210 {
211   S<<"\tSensitiveFace 3D :"<<endl;;
212   if(HasLocation())
213     S<<"\t\tExisting Location"<<endl;
214
215   if(mytype==Select3D_TOS_BOUNDARY)
216     S<<"\t\tSelection Of Bounding Polyline Only"<<endl;
217
218   if(FullDump)
219   {
220     S<<"\t\tNumber Of Points :"<<mypolyg.Size()<<endl;
221     Select3D_SensitiveEntity::DumpBox(S,mybox2d);
222   }
223 }
224
225 //=======================================================================
226 //function : ComputeDepth
227 //purpose  :
228 //=======================================================================
229
230 Standard_Real Select3D_SensitiveFace::ComputeDepth (const gp_Lin& thePickLine,
231                                                     const Standard_Real theDepthMin,
232                                                     const Standard_Real theDepthMax) const
233 {
234   Standard_Real aDepth = Precision::Infinite();
235   Standard_Real aPointDepth;
236
237   for (Standard_Integer anIndex = 0; anIndex < mypolyg.Size()-1; ++anIndex)
238   {
239     aPointDepth = ElCLib::Parameter (thePickLine, mypolyg.Pnt(anIndex));
240     if (aPointDepth < aDepth && (aPointDepth > theDepthMin) && (aPointDepth < theDepthMax))
241     {
242       aDepth = aPointDepth;
243     }
244   }
245   return aDepth;
246 }
247
248 //=======================================================================
249 //function : ComputeDepth
250 //purpose  :
251 //=======================================================================
252
253 void Select3D_SensitiveFace::ComputeDepth(const gp_Lin& /*theEyeLine*/) const
254 {
255   // this method is obsolete.
256 }
257
258 //=======================================================================
259 //function : GetConnected
260 //purpose  :
261 //=======================================================================
262
263 Handle(Select3D_SensitiveEntity) Select3D_SensitiveFace::GetConnected(const TopLoc_Location &theLocation)
264 {
265   // Create a copy of this
266   Standard_Integer aSize = mypolyg.Size();
267   TColgp_Array1OfPnt aPoints(1, aSize);
268   for (Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
269   {
270     aPoints.SetValue(anIndex, mypolyg.Pnt(anIndex-1));
271   }
272
273   Handle(Select3D_SensitiveEntity) aNewEntity =
274     new Select3D_SensitiveFace(myOwnerId, aPoints, mytype);
275
276   if (HasLocation())
277     aNewEntity->SetLocation(Location());
278
279   aNewEntity->UpdateLocation(theLocation);
280
281   return aNewEntity;
282 }