0022627: Change OCCT memory management defaults
[occt.git] / src / Select3D / Select3D_SensitiveTriangle.cxx
CommitLineData
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 21static 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
47Select3D_SensitiveTriangle::
48Select3D_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 53Select3D_SensitivePoly(OwnerId,3),
54mytype (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
66Standard_Boolean Select3D_SensitiveTriangle::
ac04d101
SA
67Matches(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 98Standard_Boolean Select3D_SensitiveTriangle::
99Matches (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
123Standard_Boolean Select3D_SensitiveTriangle::
124Matches (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 149void 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 161gp_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
175gp_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
189Standard_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
203Standard_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
304void 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 340Standard_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
391Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::
392GetConnected(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}