0024070: OpenGL capped object-level clipping planes
[occt.git] / src / Select3D / Select3D_SensitiveSegment.cxx
1 // Created on: 1995-01-25
2 // Created by: Mister rmi
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
22
23 #include <Select3D_SensitiveSegment.ixx>
24 #include <SelectBasics_BasicTool.hxx>
25 #include <gp_Vec.hxx>
26 #include <gp_Vec2d.hxx>
27 #include <Bnd_Box2d.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <gp_Dir2d.hxx>
30 #include <gp_Lin2d.hxx>
31 #include <ElCLib.hxx>
32 #include <Extrema_ExtElC.hxx>
33 #include <Extrema_POnCurv.hxx>
34 #include <TColgp_Array1OfPnt2d.hxx>
35 #include <Precision.hxx>
36 #include <SelectBasics_ListIteratorOfListOfBox2d.hxx>
37
38 #include <CSLib_Class2d.hxx>
39
40 //=====================================================
41 // Function : Create
42 // Purpose  :Constructor
43 //=====================================================
44
45 Select3D_SensitiveSegment::
46 Select3D_SensitiveSegment(const Handle(SelectBasics_EntityOwner)& OwnerId,
47                           const gp_Pnt& FirstP,
48                           const gp_Pnt& LastP,
49                           const Standard_Integer MaxRect):
50 Select3D_SensitiveEntity(OwnerId),
51 mymaxrect(MaxRect)
52 {
53   mystart = FirstP;
54   myend = LastP;
55 }
56
57 //=====================================================
58 // Function :
59 // Purpose  :
60 //=====================================================
61
62 void Select3D_SensitiveSegment
63 ::Project(const Handle(Select3D_Projector)& aProj)
64 {
65   gp_Pnt2d aPoint2dStart;
66   gp_Pnt2d aPoint2dEnd;
67
68   if(HasLocation())
69   {
70     gp_Pnt aStart(mystart.x, mystart.y, mystart.z);
71     gp_Pnt aEnd(myend.x, myend.y, myend.z);
72     aProj->Project(aStart.Transformed(Location().Transformation()),aPoint2dStart);
73     aProj->Project(aEnd.Transformed(Location().Transformation()),aPoint2dEnd);
74   }
75   else
76   {
77     aProj->Project(mystart,aPoint2dStart);
78     aProj->Project(myend,aPoint2dEnd);
79   }
80   myprojstart = aPoint2dStart;
81   myprojend = aPoint2dEnd;
82 }
83
84 //=====================================================
85 // Function : Areas
86 // Purpose  :
87 //=====================================================
88
89 void Select3D_SensitiveSegment
90 ::Areas(SelectBasics_ListOfBox2d& theareas)
91 {
92 //  gp_Dir2d dy (0.,1.);
93   gp_Pnt2d aPStart(myprojstart.x,myprojstart.y);
94   if(aPStart.Distance(myprojend)<=Precision::Confusion())
95   {
96       Bnd_Box2d curbox;
97       curbox.Set(myprojstart);
98       theareas.Append(curbox);
99   }
100   else
101   {
102     gp_Vec2d MyVec(myprojstart,myprojend);//,VAxx(gp_Dir2d(0.,1.));
103     Standard_Real theangle = Abs(gp_Dir2d(0.,1.).Angle(gp_Vec2d(myprojstart,myprojend)));
104     if(theangle>=M_PI/2.) theangle-=M_PI/2;
105     if(theangle>=M_PI/12. && theangle <=5*M_PI/12.)
106       {
107         TColgp_Array1OfPnt2d BoxPoint (1,mymaxrect+1);
108         BoxPoint (1) = myprojstart;
109         BoxPoint(mymaxrect+1)=myprojend;
110         gp_Vec2d Vtr = MyVec/mymaxrect;
111         Standard_Integer i;
112         for ( i=2;i<=mymaxrect;i++)
113         {
114           BoxPoint (i) = BoxPoint (i-1).Translated(Vtr);
115         }
116         for (i=2;i<=mymaxrect+1;i++)
117         {
118           Bnd_Box2d curbox;
119           curbox.Set(BoxPoint(i-1));
120           curbox.Add(BoxPoint(i));
121           theareas.Append(curbox);
122         }
123       }
124     else
125       {
126         Bnd_Box2d curbox;
127         curbox.Set(myprojstart);
128         curbox.Add(myprojend);
129         theareas.Append(curbox);
130       }
131   }
132 }
133
134 //=====================================================
135 // Function : Matches
136 // Purpose  :
137 //=====================================================
138
139 Standard_Boolean Select3D_SensitiveSegment::Matches (const SelectBasics_PickArgs& thePickArgs,
140                                                      Standard_Real& theMatchDMin,
141                                                      Standard_Real& theMatchDepth)
142 {
143   gp_Pnt2d aPStart (myprojstart.x,myprojstart.y);
144   gp_Pnt2d aPEnd (myprojend.x,myprojend.y);
145   if (!SelectBasics_BasicTool::MatchSegment (aPStart, aPEnd,
146                                              thePickArgs.X(),
147                                              thePickArgs.Y(),
148                                              thePickArgs.Tolerance(),
149                                              theMatchDMin))
150   {
151     return Standard_False;
152   }
153
154   theMatchDepth = ComputeDepth (thePickArgs.PickLine());
155
156   return !thePickArgs.IsClipped (theMatchDepth);
157 }
158
159 //=====================================================
160 // Function : Matches
161 // Purpose  :
162 //=====================================================
163
164 Standard_Boolean Select3D_SensitiveSegment::
165 Matches (const Standard_Real XMin,
166          const Standard_Real YMin,
167          const Standard_Real XMax,
168          const Standard_Real YMax,
169          const Standard_Real aTol)
170 {
171   Bnd_Box2d BoundBox;
172   BoundBox.Update(XMin-aTol,YMin-aTol,XMax+aTol,YMax+aTol);
173   if(BoundBox.IsOut(myprojstart)) return Standard_False;
174   if( BoundBox.IsOut(myprojend)) return Standard_False;
175   return Standard_True;
176 }
177
178 //=======================================================================
179 //function : Matches
180 //purpose  :
181 //=======================================================================
182
183 Standard_Boolean Select3D_SensitiveSegment::
184 Matches (const TColgp_Array1OfPnt2d& aPoly,
185          const Bnd_Box2d& aBox,
186          const Standard_Real aTol)
187 {
188   Standard_Real Umin,Vmin,Umax,Vmax;
189   aBox.Get(Umin,Vmin,Umax,Vmax);
190   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
191
192   Standard_Integer RES = aClassifier2d.SiDans(myprojstart);
193   if (RES!=1) return Standard_False;
194
195   RES = aClassifier2d.SiDans(myprojend);
196   if (RES!=1) return Standard_False;
197
198   return Standard_True;
199 }
200
201
202 //=======================================================================
203 //function : GetConnected
204 //purpose  :
205 //=======================================================================
206
207 Handle(Select3D_SensitiveEntity) Select3D_SensitiveSegment::
208 GetConnected(const TopLoc_Location& aLoc)
209 {
210   Handle(Select3D_SensitiveSegment) NiouEnt =
211     new Select3D_SensitiveSegment(myOwnerId,mystart,myend,mymaxrect);
212
213   if(HasLocation()) NiouEnt->SetLocation(Location());
214   NiouEnt->UpdateLocation(aLoc);
215   return NiouEnt;
216 }
217
218 //=======================================================================
219 //function : Dump
220 //purpose  :
221 //=======================================================================
222
223 void Select3D_SensitiveSegment::Dump(Standard_OStream& S,const Standard_Boolean /*FullDump*/) const
224 {
225   S<<"\tSensitivePoint 3D :"<<endl;
226   if(HasLocation())
227     S<<"\t\tExisting Location"<<endl;
228   S<<"\t\t P1 [ "<<mystart.x<<" , "<<mystart.y <<" , "<<mystart.z <<" ]"<<endl;
229   S<<"\t\t P2 [ "<<myend.x<<" , "<<myend.y <<" , "<<myend.z <<" ]"<<endl;
230   S<<"\t\t maxrect ="<<mymaxrect<<endl;
231
232 }
233 //=======================================================================
234 //function : ComputeDepth
235 //purpose  :
236 //=======================================================================
237
238 Standard_Real Select3D_SensitiveSegment::ComputeDepth(const gp_Lin& EyeLine) const
239 {
240   gp_Pnt aP0 = mystart;
241   gp_Pnt aP1 = myend;
242
243   // if segment is degenerated (zero length), just use depth of the end
244   gp_XYZ aV = aP1.XYZ() - aP0.XYZ();
245   Standard_Real aNorm = aV.Modulus();
246   if ( aNorm <= gp::Resolution() )
247     return ElCLib::Parameter (EyeLine, aP0);
248
249   // else compute point on segment closest to the line
250   gp_Lin aLine (aP0, aV);
251   Extrema_ExtElC aTool (aLine, EyeLine, Precision::Angular());
252   if ( aTool.IsDone() && ! aTool.IsParallel() )
253   {
254     for (Standard_Integer i=1; i <= aTool.NbExt(); i++)
255     {
256       Extrema_POnCurv POL1, POL2;
257       aTool.Points (i, POL1, POL2);
258       // use point found by extrema only if it is inside segment
259       if ( POL1.Parameter() > 0. && POL1.Parameter() < aNorm )
260         return ElCLib::Parameter (EyeLine, POL1.Value());
261     }
262   }
263
264   // if extrema failed or lines are parallel, return closest of the segment ends
265   return Min (ElCLib::Parameter (EyeLine, aP0),
266               ElCLib::Parameter (EyeLine, aP1));
267 }