b311480e |
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 | |
7fd59977 |
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 ) |
4269bd1b |
36 | : Select3D_SensitiveEntity( Owner ), |
7fd59977 |
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 | //================================================================ |
4952a30a |
52 | void MeshVS_SensitivePolyhedron::Project( const Handle(Select3D_Projector)& aProjector ) |
7fd59977 |
53 | { |
7fd59977 |
54 | if( myNodes.IsNull() || myNodes2d.IsNull() ) |
55 | return; |
56 | |
57 | Standard_Integer low = myNodes->Lower(), |
58 | up = myNodes->Upper(); |
59 | |
60 | gp_Pnt pnt; |
61 | gp_Pnt2d proj; |
62 | |
63 | Standard_Boolean hasLoc = HasLocation(); |
64 | |
65 | myCenter = gp_XY( 0, 0 ); |
66 | |
67 | for( Standard_Integer i=low; i<=up; i++ ) |
68 | { |
69 | pnt = myNodes->Value( i ); |
70 | if( !hasLoc ) |
4952a30a |
71 | aProjector->Project( pnt, proj ); |
7fd59977 |
72 | else |
4952a30a |
73 | aProjector->Project( pnt.Transformed( Location().Transformation() ), proj ); |
7fd59977 |
74 | |
75 | myNodes2d->SetValue( i, proj.XY() ); |
76 | myCenter += proj.XY(); |
77 | } |
78 | |
79 | myCenter /= ( up-low+1 ); |
80 | } |
81 | |
82 | //================================================================ |
83 | // Function : GetConnected |
84 | // Purpose : |
85 | //================================================================ |
86 | Handle( Select3D_SensitiveEntity ) MeshVS_SensitivePolyhedron::GetConnected |
87 | ( const TopLoc_Location& aLocation ) |
88 | { |
89 | Handle( MeshVS_SensitivePolyhedron ) NewEnt = new |
90 | MeshVS_SensitivePolyhedron( myOwnerId, myNodes->Array1(), myTopo ); |
91 | |
92 | if( HasLocation() ) |
93 | NewEnt->SetLocation( Location() ); |
94 | |
95 | NewEnt->UpdateLocation( aLocation ); |
96 | |
97 | return NewEnt; |
98 | } |
99 | |
100 | //================================================================ |
101 | // Function : sort |
102 | // Purpose : |
103 | //================================================================ |
104 | void sort( Standard_Real& a, Standard_Real& b ) |
105 | { |
106 | if( a>b ) |
107 | { |
108 | Standard_Real temp = a; a = b; b = temp; |
109 | } |
110 | } |
111 | |
112 | //================================================================ |
113 | // Function : Matches |
114 | // Purpose : |
115 | //================================================================ |
4269bd1b |
116 | Standard_Boolean MeshVS_SensitivePolyhedron::Matches( const SelectBasics_PickArgs& thePickArgs, |
117 | Standard_Real& /*theMatchDMin*/, |
118 | Standard_Real& theMatchDepth ) |
7fd59977 |
119 | { |
120 | if( myNodes2d.IsNull() || myTopo.IsNull() ) |
121 | return Standard_False; |
122 | |
123 | Standard_Integer R1 = myTopo->Lower(), |
124 | R2 = myTopo->Upper(), |
125 | low = myNodes2d->Lower(); |
126 | |
4269bd1b |
127 | Standard_Real rTol = thePickArgs.Tolerance() * SensitivityFactor(); |
7fd59977 |
128 | |
129 | Standard_Boolean inside = Standard_False; |
130 | |
131 | // "odd-even" algorithm: with ray parallel axis of absciss and toward positive |
132 | for( Standard_Integer i=R1; i<=R2 && !inside; i++ ) |
133 | { |
134 | Standard_Integer intersect = 0, cur, next, C1 = 1, C2 = myTopo->Value( i ).Length(); |
135 | Standard_Real k, b, // y=kx+b -- equation of polygon's edge |
136 | x1, y1, x2, y2, xp; // auxiliary points |
137 | |
138 | for( Standard_Integer j=C1; j<=C2; j++ ) |
139 | { |
140 | cur = myTopo->Value( i ).Value( j ); |
141 | next = myTopo->Value( i ).Value( j<C2 ? j+1 : C1 ); |
142 | |
143 | x1 = myNodes2d->Value( low+cur ).X(), |
144 | y1 = myNodes2d->Value( low+cur ).Y(), |
145 | x2 = myNodes2d->Value( low+next ).X(), |
146 | y2 = myNodes2d->Value( low+next ).Y(); |
147 | |
148 | if( Abs( x2-x1 )<Precision::Confusion() ) |
4269bd1b |
149 | { |
7fd59977 |
150 | //vertical edge!!! |
151 | |
152 | sort( y1, y2 ); |
4269bd1b |
153 | if ( thePickArgs.Y() >= y1 - rTol && thePickArgs.Y() <= y2 + rTol && x1 > thePickArgs.X() - rTol ) |
7fd59977 |
154 | intersect++; |
155 | } |
156 | else |
4269bd1b |
157 | { |
7fd59977 |
158 | //inclined edge!!! |
159 | |
160 | k = ( y2-y1 ) / ( x2-x1 ); |
161 | b = y1 - k*x1; |
162 | |
163 | if( Abs( k )>Precision::Confusion() ) |
164 | { |
4269bd1b |
165 | xp = ( thePickArgs.Y() - b ) / k; // absciss of point of intersection |
7fd59977 |
166 | sort( x1, x2 ); |
4269bd1b |
167 | if( xp >= x1 && xp <= x2 && xp > thePickArgs.X() - rTol ) |
7fd59977 |
168 | intersect++; |
169 | } |
170 | } |
171 | } |
172 | inside = ( intersect%2 ) == 1; |
173 | } |
174 | |
175 | if( inside ) |
4952a30a |
176 | { |
4269bd1b |
177 | theMatchDepth = ComputeDepth (thePickArgs.PickLine()); |
178 | |
179 | return !thePickArgs.IsClipped(theMatchDepth); |
4952a30a |
180 | } |
4269bd1b |
181 | |
4952a30a |
182 | return Standard_False; |
7fd59977 |
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++ ) |
4269bd1b |
229 | val = Min( val, ElCLib::Parameter( |
7fd59977 |
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 | //================================================================ |
4269bd1b |
268 | void MeshVS_SensitivePolyhedron::Areas( SelectBasics_ListOfBox2d& aResult ) |
7fd59977 |
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 | } |