0024157: Parallelization of assembly part of BO
[occt.git] / src / Select3D / Select3D_SensitiveTriangle.cxx
CommitLineData
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 37static 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
63Select3D_SensitiveTriangle::
64Select3D_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 69Select3D_SensitivePoly(OwnerId,3),
70mytype (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 82Standard_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 121Standard_Boolean Select3D_SensitiveTriangle::
122Matches (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
146Standard_Boolean Select3D_SensitiveTriangle::
147Matches (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 169void 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 181gp_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
195gp_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
209Standard_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
223Standard_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 324void 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 360Standard_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
411Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::
aec37c15 412GetConnected(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}