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 | //================================================================ |
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 | //================================================================ |
4952a30a |
37 | void 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 | //================================================================ |
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 ) |
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 | //================================================================ |
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 | } |