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