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