OCC22357 Hidden face selection
[occt.git] / src / MeshVS / MeshVS_SensitivePolyhedron.cxx
1 // File:        MeshVS_SensitivePolyhedron.cxx
2 // Created:     Fri Jan 21 2005
3 // Author:      Alexander SOLOVYOV
4 // Copyright:    Open CASCADE 2005
5
6
7 #include <MeshVS_SensitivePolyhedron.ixx>
8
9 #include <MeshVS_Tool.hxx>
10 #include <CSLib_Class2d.hxx>
11 #include <ElCLib.hxx>
12
13 //================================================================
14 // Function : Constructor MeshVS_SensitivePolyhedron
15 // Purpose  :
16 //================================================================
17 MeshVS_SensitivePolyhedron::
18 MeshVS_SensitivePolyhedron( const Handle( SelectBasics_EntityOwner )& Owner,
19                             const TColgp_Array1OfPnt& Nodes,
20                             const Handle( MeshVS_HArray1OfSequenceOfInteger )& Topo )
21 : Select3D_SensitiveEntity( Owner ),  
22   myTopo( Topo )
23 {
24   Standard_Integer low = Nodes.Lower(), up = Nodes.Upper(), i;
25
26   myNodes   = new TColgp_HArray1OfPnt  ( low, up );
27   for( i=low; i<=up; i++ )
28     myNodes->SetValue( i, Nodes.Value( i ) );
29
30   myNodes2d = new TColgp_HArray1OfPnt2d( low, up );
31 }
32
33 //================================================================
34 // Function : Project
35 // Purpose  :
36 //================================================================
37 void MeshVS_SensitivePolyhedron::Project( const Handle(Select3D_Projector)& aProjector )
38 {
39   Select3D_SensitiveEntity::Project( aProjector );
40
41   if( myNodes.IsNull() || myNodes2d.IsNull() )
42     return;
43
44   Standard_Integer low = myNodes->Lower(),
45                    up  = myNodes->Upper();
46
47   gp_Pnt   pnt;
48   gp_Pnt2d proj;
49
50   Standard_Boolean hasLoc = HasLocation();
51
52   myCenter = gp_XY( 0, 0 );
53
54   for( Standard_Integer i=low; i<=up; i++ )
55   {
56     pnt = myNodes->Value( i );
57     if( !hasLoc )
58       aProjector->Project( pnt, proj );
59     else
60       aProjector->Project( pnt.Transformed( Location().Transformation() ), proj );
61
62     myNodes2d->SetValue( i, proj.XY() );
63     myCenter += proj.XY();
64   }
65
66   myCenter /= ( up-low+1 );
67 }
68
69 //================================================================
70 // Function : GetConnected
71 // Purpose  :
72 //================================================================
73 Handle( Select3D_SensitiveEntity ) MeshVS_SensitivePolyhedron::GetConnected
74     ( const TopLoc_Location& aLocation )
75 {
76   Handle( MeshVS_SensitivePolyhedron ) NewEnt = new
77     MeshVS_SensitivePolyhedron( myOwnerId, myNodes->Array1(), myTopo );
78
79   if( HasLocation() )
80     NewEnt->SetLocation( Location() );
81
82   NewEnt->UpdateLocation( aLocation );
83
84   return NewEnt;
85 }
86
87 //================================================================
88 // Function : sort
89 // Purpose  :
90 //================================================================
91 void sort( Standard_Real& a, Standard_Real& b )
92 {
93   if( a>b )
94   {
95     Standard_Real temp = a; a = b; b = temp;
96   }
97 }
98
99 //================================================================
100 // Function : Matches
101 // Purpose  :
102 //================================================================
103 Standard_Boolean MeshVS_SensitivePolyhedron::Matches( const Standard_Real X,
104                                                       const Standard_Real Y,
105                                                       const Standard_Real aTol,
106                                                       Standard_Real& DMin )
107 {
108   if( myNodes2d.IsNull() || myTopo.IsNull() )
109     return Standard_False;
110
111   Standard_Integer R1  = myTopo->Lower(),
112                    R2  = myTopo->Upper(),
113                    low = myNodes2d->Lower();
114
115   Standard_Real rTol = aTol*SensitivityFactor();
116
117   Standard_Boolean inside = Standard_False;
118
119   // "odd-even" algorithm: with ray parallel axis of absciss and toward positive
120   for( Standard_Integer i=R1; i<=R2 && !inside; i++ )
121   {
122     Standard_Integer intersect = 0, cur, next, C1 = 1, C2 = myTopo->Value( i ).Length();
123     Standard_Real k, b,                         // y=kx+b -- equation of polygon's edge
124                   x1, y1, x2, y2, xp;           // auxiliary points
125
126     for( Standard_Integer j=C1; j<=C2; j++ )
127     {
128       cur = myTopo->Value( i ).Value( j );
129       next = myTopo->Value( i ).Value( j<C2 ? j+1 : C1 );
130
131       x1 = myNodes2d->Value( low+cur ).X(),
132       y1 = myNodes2d->Value( low+cur ).Y(),
133       x2 = myNodes2d->Value( low+next ).X(),
134       y2 = myNodes2d->Value( low+next ).Y();
135
136       if( Abs( x2-x1 )<Precision::Confusion() )
137       {  
138         //vertical edge!!!
139
140         sort( y1, y2 );
141         if( Y>=y1-rTol && Y<=y2+rTol && x1>X-rTol )
142           intersect++;
143       }
144       else
145       {  
146         //inclined edge!!!
147
148         k = ( y2-y1 ) / ( x2-x1 );
149         b = y1 - k*x1;
150
151         if( Abs( k )>Precision::Confusion() )
152         {
153           xp = ( Y-b ) / k; // absciss of point of intersection
154           sort( x1, x2 );
155           if( xp>=x1 && xp<=x2 && xp>X-rTol )
156             intersect++;
157         }
158       }
159     }
160     inside = ( intersect%2 ) == 1;
161   }
162
163   if( inside )
164   {
165     return Select3D_SensitiveEntity::Matches( X, Y, aTol, DMin );
166   }
167   return Standard_False;
168 }
169
170 //================================================================
171 // Function : Matches
172 // Purpose  :
173 //================================================================
174 Standard_Boolean MeshVS_SensitivePolyhedron::Matches( const Standard_Real XMin,
175                                                       const Standard_Real YMin,
176                                                       const Standard_Real XMax,
177                                                       const Standard_Real YMax,
178                                                       const Standard_Real aTol )
179 {
180   Standard_Real rTol = aTol*SensitivityFactor();
181
182   return myCenter.X()>=XMin-rTol && myCenter.X()<=XMax+rTol &&
183          myCenter.Y()>=YMin-rTol && myCenter.Y()<=YMax+rTol;
184 }
185
186 //================================================================
187 // Function : Matches
188 // Purpose  :
189 //================================================================
190 Standard_Boolean MeshVS_SensitivePolyhedron::Matches
191     ( const TColgp_Array1OfPnt2d& Polyline,
192       const Bnd_Box2d& aBox,
193       const Standard_Real aTol )
194 {
195   Standard_Real Umin, Vmin, Umax, Vmax;
196   aBox.Get( Umin, Vmin, Umax, Vmax );
197
198   CSLib_Class2d aClassifier2d( Polyline, aTol, aTol, Umin, Vmin, Umax, Vmax );
199
200   Standard_Integer res = aClassifier2d.SiDans( myCenter );
201   return( res==1 );
202 }
203
204 //================================================================
205 // Function : FindIntersection
206 // Purpose  :
207 //================================================================
208 Standard_Real MeshVS_SensitivePolyhedron::FindIntersection
209     ( const TColStd_SequenceOfInteger& NodesIndices,
210       const gp_Lin& EyeLine) const
211 {
212   Standard_Real val( Precision::Infinite() );
213   for( Standard_Integer i=1, n=NodesIndices.Length(); i<=n; i++ )
214     val = Min( val, ElCLib::Parameter( 
215       EyeLine, myNodes->Value( myNodes->Lower()+NodesIndices.Value( i ) ) ) );
216
217   return val;
218 }
219
220 //================================================================
221 // Function : ComputeDepth
222 // Purpose  :
223 //================================================================
224 Standard_Real MeshVS_SensitivePolyhedron::ComputeDepth( const gp_Lin& EyeLine ) const
225 {
226   Standard_Real val = Precision::Infinite();
227
228   if( !myTopo.IsNull() )
229     for( Standard_Integer i=myTopo->Lower(), up=myTopo->Upper(); i<=up; i++ )
230       val = Min( val, FindIntersection( myTopo->Value( i ), EyeLine ) );
231
232   return val;
233 }
234
235 //================================================================
236 // Function : ComputeSize
237 // Purpose  :
238 //================================================================
239 /*Standard_Real MeshVS_SensitivePolyhedron::ComputeSize() const
240 {
241   Bnd_Box2d aBox;
242   GetBox2d( aBox );
243
244   Standard_Real aXmin, aYmin, aXmax, aYmax;
245   aBox.Get( aXmin, aYmin, aXmax, aYmax );
246   return Abs( ( aXmax-aXmin ) * ( aYmax-aYmin ) );
247 } */
248
249 //================================================================
250 // Function : Areas
251 // Purpose  :
252 //================================================================
253 void MeshVS_SensitivePolyhedron::Areas( SelectBasics_ListOfBox2d& aResult ) 
254 {
255   Bnd_Box2d aBox;
256   GetBox2d( aBox );
257   aResult.Append( aBox );
258 }
259
260 //================================================================
261 // Function : GetBox2d
262 // Purpose  :
263 //================================================================
264 void MeshVS_SensitivePolyhedron::GetBox2d( Bnd_Box2d& aBox ) const
265 {
266   aBox.SetVoid();
267
268   Standard_Real xmin = 0., ymin = 0., xmax = 0., ymax = 0., x, y;
269   Standard_Integer low = myNodes2d->Lower(),
270                    up  = myNodes2d->Upper();
271
272   if( !myNodes2d.IsNull() )
273   {
274     xmin = xmax = myNodes2d->Value( low ).X();
275     ymin = ymax = myNodes2d->Value( low ).Y();
276     for( Standard_Integer i=low+1; i<=up; i++ )
277     {
278       x = myNodes2d->Value( i ).X();
279       y = myNodes2d->Value( i ).Y();
280       if( x>xmax )
281         xmax = x;
282       else if( x<xmin )
283         xmin = x;
284       if( y>ymax )
285         ymax = y;
286       else if( y<ymin )
287         ymin = y;
288     }
289   }
290
291   aBox.Update( xmin, ymin, xmax, ymax );
292 }