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