0024650: Wrong intersection curves obtained for a surface of revolution and a plane.
[occt.git] / src / Select3D / Select3D_SensitiveCurve.cxx
1 // Created on: 1995-03-13
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Select3D_SensitiveCurve.ixx>
18 #include <SelectBasics_BasicTool.hxx>
19 #include <gp_Lin2d.hxx>
20 #include <Precision.hxx>
21 #include <ElCLib.hxx>
22 #include <CSLib_Class2d.hxx>
23
24
25 //==================================================
26 // Function: Creation
27 // Purpose :
28 //==================================================
29
30 Select3D_SensitiveCurve
31 ::Select3D_SensitiveCurve(const Handle(SelectBasics_EntityOwner)& OwnerId,
32                           const Handle(Geom_Curve)& C,
33                           const Standard_Integer NbPoints):
34 Select3D_SensitivePoly(OwnerId, NbPoints),
35 mylastseg(0),
36 myCurve(C)
37 {
38   LoadPoints(C,NbPoints);
39 }
40
41 //==================================================
42 // Function: Creation
43 // Purpose :
44 //==================================================
45
46 Select3D_SensitiveCurve
47 ::Select3D_SensitiveCurve(const Handle(SelectBasics_EntityOwner)& OwnerId,
48                           const Handle(TColgp_HArray1OfPnt)& ThePoints):
49 Select3D_SensitivePoly(OwnerId, ThePoints),
50 mylastseg(0)
51 {
52 }
53
54 //==================================================
55 // Function: Creation
56 // Purpose :
57 //==================================================
58
59 Select3D_SensitiveCurve
60 ::Select3D_SensitiveCurve(const Handle(SelectBasics_EntityOwner)& OwnerId,
61                           const TColgp_Array1OfPnt& ThePoints):
62 Select3D_SensitivePoly(OwnerId, ThePoints),
63 mylastseg(0)
64 {
65 }
66
67 //==================================================
68 // Function: Matches
69 // Purpose :
70 //==================================================
71
72 Standard_Boolean Select3D_SensitiveCurve::Matches (const SelectBasics_PickArgs& thePickArgs,
73                                                    Standard_Real& theMatchDMin,
74                                                    Standard_Real& theMatchDepth)
75 {
76   Standard_Integer Rank;
77   TColgp_Array1OfPnt2d aArrayOf2dPnt(1, mypolyg.Size());
78   Points2D(aArrayOf2dPnt);
79   if (SelectBasics_BasicTool::MatchPolyg2d (aArrayOf2dPnt,
80                                             thePickArgs.X(), thePickArgs.Y(),
81                                             thePickArgs.Tolerance(),
82                                             theMatchDMin,
83                                             Rank))
84   {
85     // remember detected segment (for GetLastDetected)
86     mylastseg = Rank;
87
88     theMatchDepth = ComputeDepth (thePickArgs.PickLine(), Rank);
89
90     return !thePickArgs.IsClipped (theMatchDepth);
91   }
92
93   return Standard_False;
94 }
95
96 //==================================================
97 // Function: Matches
98 // Purpose : know if a box touches the projected polygon
99 //           of the Curve.
100 //==================================================
101
102 Standard_Boolean Select3D_SensitiveCurve::
103 Matches (const Standard_Real XMin,
104          const Standard_Real YMin,
105          const Standard_Real XMax,
106          const Standard_Real YMax,
107          const Standard_Real aTol)
108 {
109   Bnd_Box2d BoundBox;
110   BoundBox.Update(XMin-aTol,YMin-aTol,XMax+aTol,YMax+aTol);
111
112   for(Standard_Integer anIndex=0; anIndex<mypolyg.Size(); ++anIndex)
113     {
114       if(BoundBox.IsOut(mypolyg.Pnt2d(anIndex)))
115         return Standard_False;
116     }
117   return Standard_True;
118 }
119
120 //=======================================================================
121 //function : Matches
122 //purpose  :
123 //=======================================================================
124
125 Standard_Boolean Select3D_SensitiveCurve::
126 Matches (const TColgp_Array1OfPnt2d& aPoly,
127          const Bnd_Box2d& aBox,
128          const Standard_Real aTol)
129 {
130   Standard_Real Umin,Vmin,Umax,Vmax;
131   aBox.Get(Umin,Vmin,Umax,Vmax);
132   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
133
134   for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
135   {
136     Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
137     if(RES!=1)
138       return Standard_False;
139   }
140   return Standard_True;
141 }
142
143 //==================================================
144 // Function: LoadPoints
145 // Purpose :
146 //==================================================
147
148 void Select3D_SensitiveCurve
149 ::LoadPoints (const Handle(Geom_Curve)& aCurve,const Standard_Integer NbP)
150 {
151   /*this method is private and it used only inside of constructor.
152     That's why check !NbP==mypolyg3d->Length() was removed*/
153
154   Standard_Real Step = (aCurve->LastParameter()- aCurve->FirstParameter())/(NbP-1);
155   Standard_Real Curparam = aCurve->FirstParameter();
156   for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
157   {
158     mypolyg.SetPnt(anIndex, aCurve->Value(Curparam));
159     Curparam+=Step;
160   }
161 }
162
163 //=======================================================================
164 //function : Dump
165 //purpose  :
166 //=======================================================================
167
168 void Select3D_SensitiveCurve::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
169 {
170   S<<"\tSensitiveCurve 3D :"<<endl;
171   if (HasLocation())
172     S<<"\t\tExisting Location"<<endl;
173
174   S<<"\t\tNumber Of Points :"<<mypolyg.Size()<<endl;
175
176   if(FullDump)
177   {
178     Select3D_SensitiveEntity::DumpBox(S,mybox2d);
179   }
180 }
181
182 //=======================================================================
183 //function : ComputeDepth
184 //purpose  :
185 //=======================================================================
186
187 Standard_Real Select3D_SensitiveCurve::ComputeDepth (const gp_Lin& thePickLine,
188                                                      const Standard_Integer theSegment) const
189 {
190   if (theSegment == 0)
191   {
192     return Precision::Infinite();
193   }
194
195   // In case if theSegment and theSegment + 1 are not valid
196   // the depth will be infinite
197   if (theSegment >= mypolyg.Size())
198   {
199     return Precision::Infinite();
200   }
201
202   gp_XYZ aCDG = mypolyg.Pnt (theSegment);
203
204   if (theSegment + 1 < mypolyg.Size())
205   {
206     aCDG += mypolyg.Pnt(theSegment + 1);
207     aCDG /= 2.;
208   }
209
210   return ElCLib::Parameter (thePickLine, gp_Pnt (aCDG));
211 }
212
213 //=======================================================================
214 //function : GetConnected
215 //purpose  :
216 //=======================================================================
217
218 Handle(Select3D_SensitiveEntity) Select3D_SensitiveCurve::GetConnected(const TopLoc_Location &theLocation)
219 {
220   // Create a copy of this
221   Handle(Select3D_SensitiveEntity) aNewEntity;
222   // this was constructed using Handle(Geom_Curve)
223   if (!myCurve.IsNull())
224   {
225     aNewEntity = new Select3D_SensitiveCurve(myOwnerId, myCurve);
226   }
227   // this was constructed using TColgp_HArray1OfPnt
228   else
229   {
230     Standard_Integer aSize = mypolyg.Size();
231     Handle(TColgp_HArray1OfPnt) aPoints = new TColgp_HArray1OfPnt(1, aSize);
232     // Fill the array with points from mypolyg3d
233     for (Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
234     {
235       aPoints->SetValue(anIndex, mypolyg.Pnt(anIndex-1));
236     }
237      aNewEntity = new Select3D_SensitiveCurve(myOwnerId, aPoints);
238   }
239
240   if (HasLocation())
241     aNewEntity->SetLocation(Location());
242
243   aNewEntity->UpdateLocation(theLocation);
244
245   return aNewEntity;
246 }