1 // Created on: 2005-01-21
2 // Created by: Alexander SOLOVYOV
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <MeshVS_SensitivePolyhedron.ixx>
18 #include <MeshVS_Tool.hxx>
19 #include <CSLib_Class2d.hxx>
22 //================================================================
23 // Function : Constructor MeshVS_SensitivePolyhedron
25 //================================================================
26 MeshVS_SensitivePolyhedron::
27 MeshVS_SensitivePolyhedron( const Handle( SelectBasics_EntityOwner )& Owner,
28 const TColgp_Array1OfPnt& Nodes,
29 const Handle( MeshVS_HArray1OfSequenceOfInteger )& Topo )
30 : Select3D_SensitiveEntity( Owner ),
33 Standard_Integer low = Nodes.Lower(), up = Nodes.Upper(), i;
35 myNodes = new TColgp_HArray1OfPnt ( low, up );
36 for( i=low; i<=up; i++ )
37 myNodes->SetValue( i, Nodes.Value( i ) );
39 myNodes2d = new TColgp_HArray1OfPnt2d( low, up );
42 //================================================================
45 //================================================================
46 void MeshVS_SensitivePolyhedron::Project( const Handle(Select3D_Projector)& aProjector )
48 if( myNodes.IsNull() || myNodes2d.IsNull() )
51 Standard_Integer low = myNodes->Lower(),
52 up = myNodes->Upper();
57 Standard_Boolean hasLoc = HasLocation();
59 myCenter = gp_XY( 0, 0 );
61 for( Standard_Integer i=low; i<=up; i++ )
63 pnt = myNodes->Value( i );
65 aProjector->Project( pnt, proj );
67 aProjector->Project( pnt.Transformed( Location().Transformation() ), proj );
69 myNodes2d->SetValue( i, proj.XY() );
70 myCenter += proj.XY();
73 myCenter /= ( up-low+1 );
76 //================================================================
77 // Function : GetConnected
79 //================================================================
80 Handle( Select3D_SensitiveEntity ) MeshVS_SensitivePolyhedron::GetConnected
81 ( const TopLoc_Location& aLocation )
83 Handle( MeshVS_SensitivePolyhedron ) NewEnt = new
84 MeshVS_SensitivePolyhedron( myOwnerId, myNodes->Array1(), myTopo );
87 NewEnt->SetLocation( Location() );
89 NewEnt->UpdateLocation( aLocation );
94 //================================================================
97 //================================================================
98 void sort( Standard_Real& a, Standard_Real& b )
102 Standard_Real temp = a; a = b; b = temp;
106 //================================================================
107 // Function : Matches
109 //================================================================
110 Standard_Boolean MeshVS_SensitivePolyhedron::Matches( const SelectBasics_PickArgs& thePickArgs,
111 Standard_Real& /*theMatchDMin*/,
112 Standard_Real& theMatchDepth )
114 if( myNodes2d.IsNull() || myTopo.IsNull() )
115 return Standard_False;
117 Standard_Integer R1 = myTopo->Lower(),
118 R2 = myTopo->Upper(),
119 low = myNodes2d->Lower();
121 Standard_Real rTol = thePickArgs.Tolerance() * SensitivityFactor();
123 Standard_Boolean inside = Standard_False;
125 // "odd-even" algorithm: with ray parallel axis of absciss and toward positive
126 for( Standard_Integer i=R1; i<=R2 && !inside; i++ )
128 Standard_Integer intersect = 0, cur, next, C1 = 1, C2 = myTopo->Value( i ).Length();
129 Standard_Real k, b, // y=kx+b -- equation of polygon's edge
130 x1, y1, x2, y2, xp; // auxiliary points
132 for( Standard_Integer j=C1; j<=C2; j++ )
134 cur = myTopo->Value( i ).Value( j );
135 next = myTopo->Value( i ).Value( j<C2 ? j+1 : C1 );
137 x1 = myNodes2d->Value( low+cur ).X(),
138 y1 = myNodes2d->Value( low+cur ).Y(),
139 x2 = myNodes2d->Value( low+next ).X(),
140 y2 = myNodes2d->Value( low+next ).Y();
142 if( Abs( x2-x1 )<Precision::Confusion() )
147 if ( thePickArgs.Y() >= y1 - rTol && thePickArgs.Y() <= y2 + rTol && x1 > thePickArgs.X() - rTol )
154 k = ( y2-y1 ) / ( x2-x1 );
157 if( Abs( k )>Precision::Confusion() )
159 xp = ( thePickArgs.Y() - b ) / k; // absciss of point of intersection
161 if( xp >= x1 && xp <= x2 && xp > thePickArgs.X() - rTol )
166 inside = ( intersect%2 ) == 1;
171 theMatchDepth = ComputeDepth (thePickArgs.PickLine());
173 return !thePickArgs.IsClipped(theMatchDepth);
176 return Standard_False;
179 //================================================================
180 // Function : Matches
182 //================================================================
183 Standard_Boolean MeshVS_SensitivePolyhedron::Matches( const Standard_Real XMin,
184 const Standard_Real YMin,
185 const Standard_Real XMax,
186 const Standard_Real YMax,
187 const Standard_Real aTol )
189 Standard_Real rTol = aTol*SensitivityFactor();
191 return myCenter.X()>=XMin-rTol && myCenter.X()<=XMax+rTol &&
192 myCenter.Y()>=YMin-rTol && myCenter.Y()<=YMax+rTol;
195 //================================================================
196 // Function : Matches
198 //================================================================
199 Standard_Boolean MeshVS_SensitivePolyhedron::Matches
200 ( const TColgp_Array1OfPnt2d& Polyline,
201 const Bnd_Box2d& aBox,
202 const Standard_Real aTol )
204 Standard_Real Umin, Vmin, Umax, Vmax;
205 aBox.Get( Umin, Vmin, Umax, Vmax );
207 CSLib_Class2d aClassifier2d( Polyline, aTol, aTol, Umin, Vmin, Umax, Vmax );
209 Standard_Integer res = aClassifier2d.SiDans( myCenter );
213 //================================================================
214 // Function : FindIntersection
216 //================================================================
217 Standard_Real MeshVS_SensitivePolyhedron::FindIntersection
218 ( const TColStd_SequenceOfInteger& NodesIndices,
219 const gp_Lin& EyeLine) const
221 Standard_Real val( Precision::Infinite() );
222 for( Standard_Integer i=1, n=NodesIndices.Length(); i<=n; i++ )
223 val = Min( val, ElCLib::Parameter(
224 EyeLine, myNodes->Value( myNodes->Lower()+NodesIndices.Value( i ) ) ) );
229 //================================================================
230 // Function : ComputeDepth
232 //================================================================
233 Standard_Real MeshVS_SensitivePolyhedron::ComputeDepth( const gp_Lin& EyeLine ) const
235 Standard_Real val = Precision::Infinite();
237 if( !myTopo.IsNull() )
238 for( Standard_Integer i=myTopo->Lower(), up=myTopo->Upper(); i<=up; i++ )
239 val = Min( val, FindIntersection( myTopo->Value( i ), EyeLine ) );
244 //================================================================
245 // Function : ComputeSize
247 //================================================================
248 /*Standard_Real MeshVS_SensitivePolyhedron::ComputeSize() const
253 Standard_Real aXmin, aYmin, aXmax, aYmax;
254 aBox.Get( aXmin, aYmin, aXmax, aYmax );
255 return Abs( ( aXmax-aXmin ) * ( aYmax-aYmin ) );
258 //================================================================
261 //================================================================
262 void MeshVS_SensitivePolyhedron::Areas( SelectBasics_ListOfBox2d& aResult )
266 aResult.Append( aBox );
269 //================================================================
270 // Function : GetBox2d
272 //================================================================
273 void MeshVS_SensitivePolyhedron::GetBox2d( Bnd_Box2d& aBox ) const
277 Standard_Real xmin = 0., ymin = 0., xmax = 0., ymax = 0., x, y;
278 Standard_Integer low = myNodes2d->Lower(),
279 up = myNodes2d->Upper();
281 if( !myNodes2d.IsNull() )
283 xmin = xmax = myNodes2d->Value( low ).X();
284 ymin = ymax = myNodes2d->Value( low ).Y();
285 for( Standard_Integer i=low+1; i<=up; i++ )
287 x = myNodes2d->Value( i ).X();
288 y = myNodes2d->Value( i ).Y();
300 aBox.Update( xmin, ymin, xmax, ymax );