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
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.
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.
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.
23 #include <Select3D_SensitiveTriangle.ixx>
26 #include <SelectBasics_BasicTool.hxx>
27 #include <gp_Pnt2d.hxx>
29 #include <gp_Dir2d.hxx>
30 #include <Precision.hxx>
31 #include <Bnd_Box.hxx>
33 #include <TopLoc_Location.hxx>
35 #include <CSLib_Class2d.hxx>
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)
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;
52 gp_XY N01 (-V01.Y(),V01.X());
54 aDMin = Abs (Vec * N01);
58 //==================================================
61 //==================================================
63 Select3D_SensitiveTriangle::
64 Select3D_SensitiveTriangle(const Handle(SelectBasics_EntityOwner)& OwnerId,
68 const Select3D_TypeOfSensitivity aType):
69 Select3D_SensitivePoly(OwnerId,3),
72 mypolyg.SetPnt(0, P0);
73 mypolyg.SetPnt(1, P1);
74 mypolyg.SetPnt(2, P2);
77 //==================================================
80 //==================================================
82 Standard_Boolean Select3D_SensitiveTriangle::
83 Matches(const Standard_Real X,
84 const Standard_Real Y,
85 const Standard_Real aTol,
88 Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
89 if(Bnd_Box2d(mybox2d).IsOut(gp_Pnt2d(X,Y))) return Standard_False;
94 case Select3D_TOS_BOUNDARY:
95 Res = Status(X,Y,aTol,DMin);
98 case Select3D_TOS_INTERIOR:
99 Res = Status(X,Y,aTol,DMin);
100 return (Res==0 || Res == 1);
104 return Standard_True;
107 //==================================================
110 //==================================================
112 Standard_Boolean Select3D_SensitiveTriangle::
113 Matches (const Standard_Real XMin,
114 const Standard_Real YMin,
115 const Standard_Real XMax,
116 const Standard_Real YMax,
117 const Standard_Real aTol)
120 B.Update(Min(XMin,XMax)-aTol,
123 Max(YMin,YMax)+aTol);
124 for(Standard_Integer anIndex=0;anIndex<=2;++anIndex)
126 if(B.IsOut(mypolyg.Pnt2d(anIndex)))
127 return Standard_False;
129 return Standard_True;
132 //=======================================================================
135 //=======================================================================
137 Standard_Boolean Select3D_SensitiveTriangle::
138 Matches (const TColgp_Array1OfPnt2d& aPoly,
139 const Bnd_Box2d& aBox,
140 const Standard_Real aTol)
142 Standard_Real Umin,Vmin,Umax,Vmax;
143 aBox.Get(Umin,Vmin,Umax,Vmax);
144 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
146 for(Standard_Integer anIndex=0;anIndex<=2;++anIndex)
148 Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
150 return Standard_False;
152 return Standard_True;
155 //==================================================
156 // Function: Points3D
158 //==================================================
160 void Select3D_SensitiveTriangle::Points3D(gp_Pnt& P0,gp_Pnt& P1,gp_Pnt& P2) const
167 //==================================================
168 // Function: Center3D
170 //==================================================
172 gp_Pnt Select3D_SensitiveTriangle::Center3D() const
174 gp_XYZ aPnt1, aPnt2, aPnt3;
175 aPnt1 = mypolyg.Pnt(0);
176 aPnt2 = mypolyg.Pnt(1);
177 aPnt3 = mypolyg.Pnt(2);
178 return gp_Pnt((aPnt1+aPnt2+aPnt3)/3.);
181 //==================================================
182 // Function: Center2D
184 //==================================================
186 gp_XY Select3D_SensitiveTriangle::Center2D() const
188 gp_XY aPnt1, aPnt2, aPnt3;
189 aPnt1 = mypolyg.Pnt2d(0);
190 aPnt2 = mypolyg.Pnt2d(1);
191 aPnt3 = mypolyg.Pnt2d(2);
192 return (aPnt1+aPnt2+aPnt3)/3.;
195 //=======================================================================
197 //purpose : 0 = inside /1 = Boundary/ 2 = outside
198 //=======================================================================
200 Standard_Integer Select3D_SensitiveTriangle::Status(const Standard_Real X,
201 const Standard_Real Y,
202 const Standard_Real aTol,
203 Standard_Real& DMin) const
205 return Status(mypolyg.Pnt2d(0), mypolyg.Pnt2d(1), mypolyg.Pnt2d(2),
206 gp_XY(X,Y), aTol, DMin);
209 //=======================================================================
212 //=======================================================================
214 Standard_Integer Select3D_SensitiveTriangle::Status(const gp_XY& p0,
218 const Standard_Real aTol,
222 B.Update(p0.X(),p0.Y());B.Update(p1.X(),p1.Y());B.Update(p2.X(),p2.Y());
224 if(B.IsOut(TheP)) return 2;
226 // the point is classified corresponding to demi-spaces limited
227 // by each side of the triangle (with tolerance)
228 gp_XY V01(p1);V01-=p0;
229 gp_XY V02(p2);V02-=p0;
230 gp_XY V12(p2);V12-=p1;
232 // check these particular cases...
233 // if one of vectors is almost null (2 points are mixed),
234 // leave at once (it is already in the bounding box, which is good...)
238 if ( V01.SquareModulus() <= gp::Resolution() )
240 Standard_Real LV = V02.SquareModulus();
241 if ( LV <= gp::Resolution())
242 return 0; // 3 points are mixed, and TheP is in the bounding box B...
244 if ( S3D_Str_NearSegment (p0, p2, TheP, aTol, DMin) )
248 if ( V02.SquareModulus() <= gp::Resolution() )
250 if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
254 if ( V12.SquareModulus() <= gp::Resolution() )
256 if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
260 if ( V01.CrossMagnitude(V02) <= gp::Resolution() )
262 if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
267 // oriented normal to p0p1...
268 gp_Dir2d N (-V01.Y(), V01.X());
269 Standard_Boolean Neg = (N * V02 < 0.);
276 Standard_Real aD1 = Vec * N.XY();
280 // oriented normal to p1p2...
282 N.SetCoord(p2.Y()-p1.Y(),p1.X()-p2.X());
284 N.SetCoord(p1.Y()-p2.Y(),p2.X()-p1.X());
286 Vec.SetCoord(TheP.X()-p1.X(),TheP.Y()-p1.Y());
287 Standard_Real aD2 = Vec * N.XY();
291 // oriented normal to p2p0...
292 // attention v20 (x0-x2) => N y2-y0 => -N y0-y2
293 // (y0-y2) x0-x2 x2-x0
295 N.SetCoord(p0.Y()-p2.Y(),p2.X()-p0.X());
297 N.SetCoord(p2.Y()-p0.Y(),p0.X()-p2.X());
299 Vec.SetCoord(TheP.X()-p2.X(),TheP.Y()-p2.Y());
300 Standard_Real aD3 = Vec * N.XY();
304 // compute 2d distance to triangle
305 Standard_Real aD = Min (aD1, Min (aD2, aD3));
306 DMin = ( aD < 0 ? -aD : 0. );
310 //=======================================================================
313 //=======================================================================
315 void Select3D_SensitiveTriangle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
317 // general information....
319 S<<"\tSensitiveTriangle 3D :\n";
321 S<<"\t\tExisting Location"<<endl;
323 gp_Pnt aPnt1, aPnt2, aPnt3;
324 aPnt1 = mypolyg.Pnt(0);
325 aPnt2 = mypolyg.Pnt(1);
326 aPnt3 = mypolyg.Pnt(2);
327 S<<"\t\t P0 [ "<<aPnt1.X()<<" , "<<aPnt1.Y()<<" , "<<aPnt1.Z()<<" ]"<<endl;
328 S<<"\t\t P1 [ "<<aPnt2.X()<<" , "<<aPnt2.Y()<<" , "<<aPnt2.Z()<<" ]"<<endl;
329 S<<"\t\t P2 [ "<<aPnt3.X()<<" , "<<aPnt3.Y()<<" , "<<aPnt3.Z()<<" ]"<<endl;
333 S<<"\t\tProjected Points"<<endl;
335 gp_Pnt2d aPnt1, aPnt2, aPnt3;
336 aPnt1 = mypolyg.Pnt2d(0);
337 aPnt2 = mypolyg.Pnt2d(1);
338 aPnt3 = mypolyg.Pnt2d(2);
339 S<<"\t\t 0.[ "<<aPnt1.X()<<" , "<<aPnt1.Y()<<" ]"<<endl;
340 S<<"\t\t 1.[ "<<aPnt2.X()<<" , "<<aPnt2.Y()<<" ]"<<endl;
341 S<<"\t\t 2.[ "<<aPnt3.X()<<" , "<<aPnt3.Y()<<" ]"<<endl;
342 Select3D_SensitiveEntity::DumpBox(S,mybox2d);
346 //=======================================================================
347 //function : ComputeDepth
349 //=======================================================================
351 Standard_Real Select3D_SensitiveTriangle::ComputeDepth(const gp_Lin& EyeLine) const
353 Standard_Real prof(Precision::Infinite());
362 TheTrsf = Location().Transformation();
364 if(TheTrsf.Form()!=gp_Identity)
366 P1.Transform(TheTrsf);
367 P2.Transform(TheTrsf);
368 P3.Transform(TheTrsf);
371 // formula calculation of the point parameters on intersection
372 // t = (P1P2 ^P1P3)* OP1 / ((P1P2^P1P3)*Dir)
374 gp_Pnt Oye = EyeLine.Location(); // origin of the target line eye/point...
375 gp_Dir Dir = EyeLine.Direction();
377 gp_Vec P1P2 (P1,P2), P1P3(P1,P3);
382 Standard_Real val1 = oP1.DotCross(P1P2,P1P3);
383 Standard_Real val2 = Dir.DotCross(P1P2,P1P3);
385 if(Abs(val2)>Precision::Confusion())
388 if (prof==Precision::Infinite())
390 prof= ElCLib::Parameter(EyeLine,P1);
391 prof = Min (prof, ElCLib::Parameter(EyeLine,P2));
392 prof = Min (prof, ElCLib::Parameter(EyeLine,P3));
397 //==================================================
398 // Function: GetConnected
400 //==================================================
402 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::
403 GetConnected(const TopLoc_Location &theLocation)
405 // Create a copy of this
406 Handle(Select3D_SensitiveEntity) aNewEntity =
407 new Select3D_SensitiveTriangle(myOwnerId, mypolyg.Pnt(0), mypolyg.Pnt(1), mypolyg.Pnt(2), mytype);
410 aNewEntity->SetLocation(Location());
412 aNewEntity->UpdateLocation(theLocation);