Commit | Line | Data |
---|---|---|
7fd59977 | 1 | // File: Select3D_SensitiveTriangle.cxx |
2 | // Created: Wed May 14 16:56:06 1997 | |
3 | // Author: Robert COUBLANC | |
4 | // <rob@robox.paris1.matra-dtv.fr> | |
5 | ||
6 | ||
7 | #include <Select3D_SensitiveTriangle.ixx> | |
8 | ||
9 | ||
10 | #include <SelectBasics_BasicTool.hxx> | |
11 | #include <gp_Pnt2d.hxx> | |
12 | #include <gp_Pnt.hxx> | |
13 | #include <gp_Dir2d.hxx> | |
14 | #include <Precision.hxx> | |
15 | #include <Bnd_Box.hxx> | |
16 | #include <ElCLib.hxx> | |
17 | #include <TopLoc_Location.hxx> | |
18 | ||
19 | #include <CSLib_Class2d.hxx> | |
20 | ||
7fd59977 | 21 | static Standard_Boolean S3D_Str_NearSegment (const gp_XY& p0, const gp_XY& p1, const gp_XY& TheP, |
22 | const Standard_Real aTol, Standard_Real& aDMin) | |
23 | { | |
24 | gp_XY V01(p1); | |
25 | V01 -= p0; | |
26 | ||
27 | gp_XY Vec(TheP); | |
28 | Vec -= p0; | |
29 | ||
30 | Standard_Real u = Vec*V01.Normalized(); | |
31 | if(u<-aTol) return Standard_False; | |
32 | Standard_Real u1 = u-aTol; | |
33 | Standard_Real modmod = V01.SquareModulus(); | |
34 | if(u1*u1> modmod) return Standard_False; | |
35 | ||
36 | gp_XY N01 (-V01.Y(),V01.X()); | |
37 | N01.Normalize(); | |
38 | aDMin = Abs (Vec * N01); | |
39 | return aDMin <= aTol; | |
40 | } | |
41 | ||
42 | //================================================== | |
ac04d101 | 43 | // Function: Creation |
7fd59977 | 44 | // Purpose : |
45 | //================================================== | |
46 | ||
47 | Select3D_SensitiveTriangle:: | |
48 | Select3D_SensitiveTriangle(const Handle(SelectBasics_EntityOwner)& OwnerId, | |
ac04d101 SA |
49 | const gp_Pnt& P0, |
50 | const gp_Pnt& P1, | |
51 | const gp_Pnt& P2, | |
52 | const Select3D_TypeOfSensitivity aType): | |
7fd59977 | 53 | Select3D_SensitivePoly(OwnerId,3), |
54 | mytype (aType) | |
ceae62f0 A |
55 | { |
56 | mypolyg.SetPnt(0, P0); | |
57 | mypolyg.SetPnt(1, P1); | |
58 | mypolyg.SetPnt(2, P2); | |
7fd59977 | 59 | } |
60 | ||
61 | //================================================== | |
ac04d101 | 62 | // Function: Matches |
7fd59977 | 63 | // Purpose : |
64 | //================================================== | |
65 | ||
66 | Standard_Boolean Select3D_SensitiveTriangle:: | |
ac04d101 SA |
67 | Matches(const Standard_Real X, |
68 | const Standard_Real Y, | |
69 | const Standard_Real aTol, | |
70 | Standard_Real& DMin) | |
7fd59977 | 71 | { |
72 | Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin); | |
73 | if(Bnd_Box2d(mybox2d).IsOut(gp_Pnt2d(X,Y))) return Standard_False; | |
74 | ||
75 | Standard_Integer Res; | |
ceae62f0 | 76 | switch (mytype) |
ac04d101 | 77 | { |
7fd59977 | 78 | case Select3D_TOS_BOUNDARY: |
79 | Res = Status(X,Y,aTol,DMin); | |
80 | return Res== 1; | |
81 | break; | |
82 | case Select3D_TOS_INTERIOR: | |
83 | Res = Status(X,Y,aTol,DMin); | |
84 | return (Res==0 || Res == 1); | |
85 | #ifndef DEB | |
86 | default: | |
87 | break; | |
ceae62f0 | 88 | #endif |
7fd59977 | 89 | } |
90 | return Standard_True; | |
91 | } | |
92 | ||
ac04d101 SA |
93 | //================================================== |
94 | // Function: Matches | |
95 | // Purpose : | |
96 | //================================================== | |
97 | ||
7fd59977 | 98 | Standard_Boolean Select3D_SensitiveTriangle:: |
99 | Matches (const Standard_Real XMin, | |
ac04d101 SA |
100 | const Standard_Real YMin, |
101 | const Standard_Real XMax, | |
102 | const Standard_Real YMax, | |
103 | const Standard_Real aTol) | |
7fd59977 | 104 | { |
105 | Bnd_Box2d B; | |
106 | B.Update(Min(XMin,XMax)-aTol, | |
ac04d101 SA |
107 | Min(YMin,YMax)-aTol, |
108 | Max(XMin,XMax)+aTol, | |
109 | Max(YMin,YMax)+aTol); | |
ceae62f0 | 110 | for(Standard_Integer anIndex=0;anIndex<=2;++anIndex) |
ac04d101 | 111 | { |
ceae62f0 | 112 | if(B.IsOut(mypolyg.Pnt2d(anIndex))) |
ac04d101 SA |
113 | return Standard_False; |
114 | } | |
7fd59977 | 115 | return Standard_True; |
116 | } | |
117 | ||
7fd59977 | 118 | //======================================================================= |
119 | //function : Matches | |
120 | //purpose : | |
121 | //======================================================================= | |
122 | ||
123 | Standard_Boolean Select3D_SensitiveTriangle:: | |
124 | Matches (const TColgp_Array1OfPnt2d& aPoly, | |
ac04d101 SA |
125 | const Bnd_Box2d& aBox, |
126 | const Standard_Real aTol) | |
ceae62f0 | 127 | { |
7fd59977 | 128 | Standard_Real Umin,Vmin,Umax,Vmax; |
129 | aBox.Get(Umin,Vmin,Umax,Vmax); | |
130 | Standard_Real Tolu,Tolv; | |
131 | Tolu = 1e-7; | |
132 | Tolv = 1e-7; | |
133 | CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax); | |
134 | ||
ceae62f0 | 135 | for(Standard_Integer anIndex=0;anIndex<=2;++anIndex) |
ac04d101 | 136 | { |
ceae62f0 A |
137 | Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex)); |
138 | if(RES!=1) | |
139 | return Standard_False; | |
7fd59977 | 140 | } |
141 | return Standard_True; | |
142 | } | |
143 | ||
ac04d101 SA |
144 | //================================================== |
145 | // Function: Points3D | |
146 | // Purpose : | |
147 | //================================================== | |
7fd59977 | 148 | |
ceae62f0 | 149 | void Select3D_SensitiveTriangle::Points3D(gp_Pnt& P0,gp_Pnt& P1,gp_Pnt& P2) const |
7fd59977 | 150 | { |
ceae62f0 A |
151 | P0 = mypolyg.Pnt(0); |
152 | P1 = mypolyg.Pnt(1); | |
153 | P2 = mypolyg.Pnt(2); | |
7fd59977 | 154 | } |
155 | ||
ac04d101 SA |
156 | //================================================== |
157 | // Function: Center3D | |
158 | // Purpose : | |
159 | //================================================== | |
160 | ||
7fd59977 | 161 | gp_Pnt Select3D_SensitiveTriangle::Center3D() const |
162 | { | |
ceae62f0 A |
163 | gp_XYZ aPnt1, aPnt2, aPnt3; |
164 | aPnt1 = mypolyg.Pnt(0); | |
165 | aPnt2 = mypolyg.Pnt(1); | |
166 | aPnt3 = mypolyg.Pnt(2); | |
167 | return gp_Pnt((aPnt1+aPnt2+aPnt3)/3.); | |
ac04d101 SA |
168 | } |
169 | ||
170 | //================================================== | |
171 | // Function: Center2D | |
172 | // Purpose : | |
173 | //================================================== | |
7fd59977 | 174 | |
175 | gp_XY Select3D_SensitiveTriangle::Center2D() const | |
176 | { | |
ceae62f0 A |
177 | gp_XY aPnt1, aPnt2, aPnt3; |
178 | aPnt1 = mypolyg.Pnt2d(0); | |
179 | aPnt2 = mypolyg.Pnt2d(1); | |
180 | aPnt3 = mypolyg.Pnt2d(2); | |
181 | return (aPnt1+aPnt2+aPnt3)/3.; | |
7fd59977 | 182 | } |
183 | ||
184 | //======================================================================= | |
185 | //function : Status | |
186 | //purpose : 0 = inside /1 = Boundary/ 2 = outside | |
187 | //======================================================================= | |
188 | ||
189 | Standard_Integer Select3D_SensitiveTriangle::Status(const Standard_Real X, | |
ac04d101 SA |
190 | const Standard_Real Y, |
191 | const Standard_Real aTol, | |
ceae62f0 A |
192 | Standard_Real& DMin) const |
193 | { | |
194 | return Status(mypolyg.Pnt2d(0), mypolyg.Pnt2d(1), mypolyg.Pnt2d(2), | |
195 | gp_XY(X,Y), aTol, DMin); | |
7fd59977 | 196 | } |
197 | ||
7fd59977 | 198 | //======================================================================= |
199 | //function : Status | |
200 | //purpose : | |
201 | //======================================================================= | |
202 | ||
203 | Standard_Integer Select3D_SensitiveTriangle::Status(const gp_XY& p0, | |
ac04d101 SA |
204 | const gp_XY& p1, |
205 | const gp_XY& p2, | |
206 | const gp_XY& TheP, | |
207 | const Standard_Real aTol, | |
208 | Standard_Real& DMin) | |
7fd59977 | 209 | { |
7fd59977 | 210 | Bnd_Box2d B; |
211 | B.Update(p0.X(),p0.Y());B.Update(p1.X(),p1.Y());B.Update(p2.X(),p2.Y()); | |
212 | B.Enlarge(aTol); | |
ceae62f0 | 213 | if(B.IsOut(TheP)) return 2; |
7fd59977 | 214 | |
81bba717 | 215 | // the point is classified corresponding to demi-spaces limited |
216 | // by each side of the triangle (with tolerance) | |
7fd59977 | 217 | gp_XY V01(p1);V01-=p0; |
218 | gp_XY V02(p2);V02-=p0; | |
219 | gp_XY V12(p2);V12-=p1; | |
220 | ||
81bba717 | 221 | // check these particular cases... |
ceae62f0 | 222 | // if one of vectors is almost null (2 points are mixed), |
81bba717 | 223 | // leave at once (it is already in the bounding box, which is good...) |
7fd59977 | 224 | |
225 | DMin = aTol; | |
226 | ||
227 | if ( V01.SquareModulus() <= gp::Resolution() ) | |
228 | { | |
229 | Standard_Real LV = V02.SquareModulus(); | |
230 | if ( LV <= gp::Resolution()) | |
81bba717 | 231 | return 0; // 3 points are mixed, and TheP is in the bounding box B... |
7fd59977 | 232 | |
233 | if ( S3D_Str_NearSegment (p0, p2, TheP, aTol, DMin) ) | |
234 | return 0; | |
235 | return 2; | |
236 | } | |
237 | if ( V02.SquareModulus() <= gp::Resolution() ) | |
238 | { | |
239 | if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) ) | |
240 | return 0; | |
241 | return 2; | |
242 | } | |
243 | if ( V12.SquareModulus() <= gp::Resolution() ) | |
244 | { | |
245 | if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) ) | |
246 | return 0; | |
247 | return 2; | |
248 | } | |
249 | if ( V01.CrossMagnitude(V02) <= gp::Resolution() ) | |
250 | { | |
251 | if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) ) | |
252 | return 0; | |
253 | return 2; | |
254 | } | |
255 | ||
81bba717 | 256 | // oriented normal to p0p1... |
7fd59977 | 257 | gp_Dir2d N (-V01.Y(), V01.X()); |
258 | Standard_Boolean Neg = (N * V02 < 0.); | |
259 | if ( Neg ) | |
260 | N.Reverse(); | |
261 | ||
262 | gp_XY Vec(TheP); | |
263 | Vec -= p0; | |
264 | ||
265 | Standard_Real aD1 = Vec * N.XY(); | |
266 | if ( aD1 < -aTol ) | |
267 | return 2; | |
268 | ||
81bba717 | 269 | // oriented normal to p1p2... |
7fd59977 | 270 | if(Neg) |
271 | N.SetCoord(p2.Y()-p1.Y(),p1.X()-p2.X()); | |
272 | else | |
273 | N.SetCoord(p1.Y()-p2.Y(),p2.X()-p1.X()); | |
274 | ||
275 | Vec.SetCoord(TheP.X()-p1.X(),TheP.Y()-p1.Y()); | |
276 | Standard_Real aD2 = Vec * N.XY(); | |
277 | if ( aD2 < -aTol ) | |
81bba717 | 278 | return 2; // outside |
7fd59977 | 279 | |
81bba717 | 280 | // oriented normal to p2p0... |
7fd59977 | 281 | // attention v20 (x0-x2) => N y2-y0 => -N y0-y2 |
282 | // (y0-y2) x0-x2 x2-x0 | |
283 | if(Neg) | |
284 | N.SetCoord(p0.Y()-p2.Y(),p2.X()-p0.X()); | |
285 | else | |
286 | N.SetCoord(p2.Y()-p0.Y(),p0.X()-p2.X()); | |
287 | ||
288 | Vec.SetCoord(TheP.X()-p2.X(),TheP.Y()-p2.Y()); | |
289 | Standard_Real aD3 = Vec * N.XY(); | |
290 | if ( aD3 < -aTol ) | |
81bba717 | 291 | return 2; // outside |
7fd59977 | 292 | |
293 | // compute 2d distance to triangle | |
294 | Standard_Real aD = Min (aD1, Min (aD2, aD3)); | |
295 | DMin = ( aD < 0 ? -aD : 0. ); | |
296 | return 0; | |
297 | } | |
ac04d101 | 298 | |
7fd59977 | 299 | //======================================================================= |
300 | //function : Dump | |
301 | //purpose : | |
302 | //======================================================================= | |
303 | ||
304 | void Select3D_SensitiveTriangle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const | |
305 | { | |
81bba717 | 306 | // general information.... |
ceae62f0 | 307 | |
7fd59977 | 308 | S<<"\tSensitiveTriangle 3D :\n"; |
309 | if(HasLocation()) | |
310 | S<<"\t\tExisting Location"<<endl; | |
311 | ||
ceae62f0 A |
312 | gp_Pnt aPnt1, aPnt2, aPnt3; |
313 | aPnt1 = mypolyg.Pnt(0); | |
314 | aPnt2 = mypolyg.Pnt(1); | |
315 | aPnt3 = mypolyg.Pnt(2); | |
316 | S<<"\t\t P0 [ "<<aPnt1.X()<<" , "<<aPnt1.Y()<<" , "<<aPnt1.Z()<<" ]"<<endl; | |
317 | S<<"\t\t P1 [ "<<aPnt2.X()<<" , "<<aPnt2.Y()<<" , "<<aPnt2.Z()<<" ]"<<endl; | |
318 | S<<"\t\t P2 [ "<<aPnt3.X()<<" , "<<aPnt3.Y()<<" , "<<aPnt3.Z()<<" ]"<<endl; | |
7fd59977 | 319 | |
ac04d101 SA |
320 | if(FullDump) |
321 | { | |
7fd59977 | 322 | S<<"\t\tProjected Points"<<endl; |
ceae62f0 A |
323 | |
324 | gp_Pnt2d aPnt1, aPnt2, aPnt3; | |
325 | aPnt1 = mypolyg.Pnt2d(0); | |
326 | aPnt2 = mypolyg.Pnt2d(1); | |
327 | aPnt3 = mypolyg.Pnt2d(2); | |
328 | S<<"\t\t 0.[ "<<aPnt1.X()<<" , "<<aPnt1.Y()<<" ]"<<endl; | |
329 | S<<"\t\t 1.[ "<<aPnt2.X()<<" , "<<aPnt2.Y()<<" ]"<<endl; | |
330 | S<<"\t\t 2.[ "<<aPnt3.X()<<" , "<<aPnt3.Y()<<" ]"<<endl; | |
7fd59977 | 331 | Select3D_SensitiveEntity::DumpBox(S,mybox2d); |
7fd59977 | 332 | } |
333 | } | |
ac04d101 | 334 | |
7fd59977 | 335 | //======================================================================= |
336 | //function : ComputeDepth | |
337 | //purpose : | |
338 | //======================================================================= | |
ac04d101 | 339 | |
7fd59977 | 340 | Standard_Real Select3D_SensitiveTriangle::ComputeDepth(const gp_Lin& EyeLine) const |
341 | { | |
ceae62f0 A |
342 | Standard_Real prof(Precision::Infinite()); |
343 | ||
344 | gp_Pnt P1, P2, P3; | |
345 | P1 = mypolyg.Pnt(0); | |
346 | P2 = mypolyg.Pnt(1); | |
347 | P3 = mypolyg.Pnt(2); | |
7fd59977 | 348 | |
349 | gp_Trsf TheTrsf ; | |
350 | if(HasLocation()) | |
351 | TheTrsf = Location().Transformation(); | |
352 | ||
ac04d101 SA |
353 | if(TheTrsf.Form()!=gp_Identity) |
354 | { | |
7fd59977 | 355 | P1.Transform(TheTrsf); |
356 | P2.Transform(TheTrsf); | |
357 | P3.Transform(TheTrsf); | |
358 | } | |
359 | ||
81bba717 | 360 | // formula calculation of the point parameters on intersection |
7fd59977 | 361 | // t = (P1P2 ^P1P3)* OP1 / ((P1P2^P1P3)*Dir) |
362 | ||
81bba717 | 363 | gp_Pnt Oye = EyeLine.Location(); // origin of the target line eye/point... |
7fd59977 | 364 | gp_Dir Dir = EyeLine.Direction(); |
365 | ||
366 | gp_Vec P1P2 (P1,P2), P1P3(P1,P3); | |
367 | P1P2.Normalize(); | |
368 | P1P3.Normalize(); | |
369 | ||
370 | gp_Vec oP1(Oye,P1); | |
371 | Standard_Real val1 = oP1.DotCross(P1P2,P1P3); | |
372 | Standard_Real val2 = Dir.DotCross(P1P2,P1P3); | |
373 | ||
374 | if(Abs(val2)>Precision::Confusion()) | |
375 | prof =val1/val2; | |
376 | ||
ac04d101 SA |
377 | if (prof==Precision::Infinite()) |
378 | { | |
7fd59977 | 379 | prof= ElCLib::Parameter(EyeLine,P1); |
380 | prof = Min (prof, ElCLib::Parameter(EyeLine,P2)); | |
381 | prof = Min (prof, ElCLib::Parameter(EyeLine,P3)); | |
382 | } | |
383 | return prof; | |
7fd59977 | 384 | } |
385 | ||
ac04d101 SA |
386 | //================================================== |
387 | // Function: GetConnected | |
388 | // Purpose : | |
389 | //================================================== | |
390 | ||
391 | Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle:: | |
392 | GetConnected(const TopLoc_Location &theLocation) | |
393 | { | |
394 | // Create a copy of this | |
395 | Handle(Select3D_SensitiveEntity) aNewEntity = | |
ceae62f0 | 396 | new Select3D_SensitiveTriangle(myOwnerId, mypolyg.Pnt(0), mypolyg.Pnt(1), mypolyg.Pnt(2), mytype); |
ac04d101 SA |
397 | |
398 | if (HasLocation()) | |
399 | aNewEntity->SetLocation(Location()); | |
400 | ||
401 | aNewEntity->UpdateLocation(theLocation); | |
402 | ||
403 | return aNewEntity; | |
404 | } |