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