0022554: Application hangs on selection
[occt.git] / src / Select3D / Select3D_SensitiveCurve.cxx
1 // Copyright:   Matra-Datavision 1995
2 // File:    Select3D_SensitiveCurve.cxx
3 // Created: Mon Mar 13 09:57:58 1995
4 // Author:  Robert COUBLANC
5 //      <rob>
6
7
8
9 #include <Select3D_SensitiveCurve.ixx>
10 #include <SelectBasics_BasicTool.hxx>
11 #include <gp_Lin2d.hxx>
12 #include <Precision.hxx>
13 #include <ElCLib.hxx>
14 #include <CSLib_Class2d.hxx>
15
16
17 //==================================================
18 // Function: Creation
19 // Purpose :
20 //==================================================
21
22 Select3D_SensitiveCurve
23 ::Select3D_SensitiveCurve(const Handle(SelectBasics_EntityOwner)& OwnerId,
24                           const Handle(Geom_Curve)& C,
25                           const Standard_Integer NbPoints):
26 Select3D_SensitivePoly(OwnerId, NbPoints),
27 mylastseg(0), 
28 myCurve(C)
29 {
30   LoadPoints(C,NbPoints);
31 }
32
33 //==================================================
34 // Function: Creation
35 // Purpose :
36 //==================================================
37
38 Select3D_SensitiveCurve
39 ::Select3D_SensitiveCurve(const Handle(SelectBasics_EntityOwner)& OwnerId,
40                           const Handle(TColgp_HArray1OfPnt)& ThePoints):
41 Select3D_SensitivePoly(OwnerId, ThePoints),
42 mylastseg(0)
43 {
44 }
45
46 //==================================================
47 // Function: Creation
48 // Purpose :
49 //==================================================
50
51 Select3D_SensitiveCurve
52 ::Select3D_SensitiveCurve(const Handle(SelectBasics_EntityOwner)& OwnerId,
53                           const TColgp_Array1OfPnt& ThePoints):
54 Select3D_SensitivePoly(OwnerId, ThePoints),
55 mylastseg(0)
56 {
57 }
58
59 //==================================================
60 // Function: Matches
61 // Purpose :
62 //==================================================
63
64 Standard_Boolean Select3D_SensitiveCurve
65 ::Matches(const Standard_Real X,
66           const Standard_Real Y,
67           const Standard_Real aTol,
68           Standard_Real& DMin)
69 {
70   Standard_Integer Rank;
71   TColgp_Array1OfPnt2d aArrayOf2dPnt(1, mypolyg.Size());
72   Points2D(aArrayOf2dPnt);
73   if (SelectBasics_BasicTool::MatchPolyg2d (aArrayOf2dPnt,
74                                             X, Y,
75                                             aTol,
76                                             DMin,
77                                             Rank))
78   {
79     mylastseg = Rank;
80     // compute and validate the depth (::Depth()) along the eyeline
81     return Select3D_SensitiveEntity::Matches (X, Y, aTol, DMin);
82   }
83   return Standard_False;
84 }
85
86 //==================================================
87 // Function: Matches
88 // Purpose : know if a box touches the projected polygon
89 //           of the Curve.
90 //==================================================
91
92 Standard_Boolean Select3D_SensitiveCurve::
93 Matches (const Standard_Real XMin,
94          const Standard_Real YMin,
95          const Standard_Real XMax,
96          const Standard_Real YMax,
97          const Standard_Real aTol)
98 {
99   Bnd_Box2d BoundBox;
100   BoundBox.Update(XMin-aTol,YMin-aTol,XMax+aTol,YMax+aTol);
101   
102   for(Standard_Integer anIndex=0; anIndex<mypolyg.Size(); ++anIndex)
103     {
104       if(BoundBox.IsOut(mypolyg.Pnt2d(anIndex)))
105         return Standard_False;
106     }
107   return Standard_True;
108 }
109
110 //=======================================================================
111 //function : Matches
112 //purpose  : 
113 //=======================================================================
114
115 Standard_Boolean Select3D_SensitiveCurve::
116 Matches (const TColgp_Array1OfPnt2d& aPoly,
117          const Bnd_Box2d& aBox,
118          const Standard_Real aTol)
119 {
120   Standard_Real Umin,Vmin,Umax,Vmax;
121   aBox.Get(Umin,Vmin,Umax,Vmax);
122   Standard_Real Tolu,Tolv;
123   Tolu = 1e-7;
124   Tolv = 1e-7;
125   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
126
127   for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
128   {
129     Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
130     if(RES!=1)
131       return Standard_False;
132   }
133   return Standard_True;
134 }
135
136 //==================================================
137 // Function: LoadPoints
138 // Purpose :
139 //==================================================
140
141 void Select3D_SensitiveCurve
142 ::LoadPoints (const Handle(Geom_Curve)& aCurve,const Standard_Integer NbP)
143 {
144   /*this method is private and it used only inside of constructor. 
145     That's why check !NbP==mypolyg3d->Length() was removed*/
146
147   Standard_Real Step = (aCurve->LastParameter()- aCurve->FirstParameter())/(NbP-1);
148   Standard_Real Curparam = aCurve->FirstParameter();
149   for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
150   {
151     mypolyg.SetPnt(anIndex, aCurve->Value(Curparam));
152     Curparam+=Step;
153   }
154 }
155
156 //=======================================================================
157 //function : Dump
158 //purpose  : 
159 //=======================================================================
160
161 void Select3D_SensitiveCurve::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const 
162 {
163   S<<"\tSensitiveCurve 3D :"<<endl;
164   if (HasLocation())
165     S<<"\t\tExisting Location"<<endl;
166
167   S<<"\t\tNumber Of Points :"<<mypolyg.Size()<<endl;
168
169   if(FullDump)
170   {
171     Select3D_SensitiveEntity::DumpBox(S,mybox2d);
172   }
173 }
174
175 //=======================================================================
176 //function : ComputeDepth
177 //purpose  : 
178 //=======================================================================
179
180 Standard_Real Select3D_SensitiveCurve::ComputeDepth(const gp_Lin& EyeLine) const
181 {
182   Standard_Real aDepth = Precision::Infinite();
183
184   // Not implemented
185   if(mylastseg==0)
186     return aDepth;
187
188   gp_XYZ aCDG;
189   // In case if mylastseg and mylastseg+1 are not valid
190   // the depth will be infinite
191   if (mylastseg < mypolyg.Size())
192   {
193     aCDG = mypolyg.Pnt(mylastseg);
194     if (mylastseg+1 < mypolyg.Size())
195     {
196       aCDG += mypolyg.Pnt(mylastseg+1);
197       aCDG /= 2.;
198     }
199     aDepth = ElCLib::Parameter(EyeLine,gp_Pnt(aCDG));
200   }
201
202   return aDepth;
203 }
204
205 //=======================================================================
206 //function : GetConnected
207 //purpose  : 
208 //======================================================================= 
209
210 Handle(Select3D_SensitiveEntity) Select3D_SensitiveCurve::GetConnected(const TopLoc_Location &theLocation) 
211 {
212   // Create a copy of this 
213   Handle(Select3D_SensitiveEntity) aNewEntity;
214   // this was constructed using Handle(Geom_Curve) 
215   if (!myCurve.IsNull()) 
216   {
217     aNewEntity = new Select3D_SensitiveCurve(myOwnerId, myCurve);
218   }
219   // this was constructed using TColgp_HArray1OfPnt
220   else 
221   {
222     Standard_Integer aSize = mypolyg.Size();
223     Handle(TColgp_HArray1OfPnt) aPoints = new TColgp_HArray1OfPnt(1, aSize);
224     // Fill the array with points from mypolyg3d
225     for (Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex) 
226     {
227       aPoints->SetValue(anIndex, mypolyg.Pnt(anIndex-1));
228     }
229      aNewEntity = new Select3D_SensitiveCurve(myOwnerId, aPoints);
230   }
231   
232   if (HasLocation()) 
233     aNewEntity->SetLocation(Location()); 
234
235   aNewEntity->UpdateLocation(theLocation);
236
237   return aNewEntity;
238 }