OCC22357 Hidden face selection
[occt.git] / src / MeshVS / MeshVS_SensitivePolyhedron.cxx
CommitLineData
7fd59977 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//================================================================
17MeshVS_SensitivePolyhedron::
18MeshVS_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//================================================================
4952a30a 37void MeshVS_SensitivePolyhedron::Project( const Handle(Select3D_Projector)& aProjector )
7fd59977 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 )
4952a30a 58 aProjector->Project( pnt, proj );
7fd59977 59 else
4952a30a 60 aProjector->Project( pnt.Transformed( Location().Transformation() ), proj );
7fd59977 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//================================================================
73Handle( 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//================================================================
91void 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//================================================================
103Standard_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 )
4952a30a 164 {
165 return Select3D_SensitiveEntity::Matches( X, Y, aTol, DMin );
166 }
167 return Standard_False;
7fd59977 168}
169
170//================================================================
171// Function : Matches
172// Purpose :
173//================================================================
174Standard_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//================================================================
190Standard_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//================================================================
208Standard_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//================================================================
224Standard_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//================================================================
253void 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//================================================================
264void 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}