mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-18 07:57:31 +08:00
400 lines
12 KiB
C++
Executable File
400 lines
12 KiB
C++
Executable File
// File: Select3D_SensitiveTriangle.cxx
|
|
// Created: Wed May 14 16:56:06 1997
|
|
// Author: Robert COUBLANC
|
|
// <rob@robox.paris1.matra-dtv.fr>
|
|
|
|
|
|
#include <Select3D_SensitiveTriangle.ixx>
|
|
|
|
|
|
#include <SelectBasics_BasicTool.hxx>
|
|
#include <gp_Pnt2d.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Dir2d.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Bnd_Box.hxx>
|
|
#include <ElCLib.hxx>
|
|
#include <TopLoc_Location.hxx>
|
|
|
|
#include <CSLib_Class2d.hxx>
|
|
|
|
#define COORD(a,b) ((Select3D_Pnt*)mypolyg3d)[(a)].b
|
|
#define COORD2d(a,b) ((Select3D_Pnt2d*)mypolyg2d)[(a)].b
|
|
|
|
static Standard_Boolean S3D_Str_NearSegment (const gp_XY& p0, const gp_XY& p1, const gp_XY& TheP,
|
|
const Standard_Real aTol, Standard_Real& aDMin)
|
|
{
|
|
gp_XY V01(p1);
|
|
V01 -= p0;
|
|
|
|
gp_XY Vec(TheP);
|
|
Vec -= p0;
|
|
|
|
Standard_Real u = Vec*V01.Normalized();
|
|
if(u<-aTol) return Standard_False;
|
|
Standard_Real u1 = u-aTol;
|
|
Standard_Real modmod = V01.SquareModulus();
|
|
if(u1*u1> modmod) return Standard_False;
|
|
|
|
gp_XY N01 (-V01.Y(),V01.X());
|
|
N01.Normalize();
|
|
aDMin = Abs (Vec * N01);
|
|
return aDMin <= aTol;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Creation
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
Select3D_SensitiveTriangle::
|
|
Select3D_SensitiveTriangle(const Handle(SelectBasics_EntityOwner)& OwnerId,
|
|
const gp_Pnt& P0,
|
|
const gp_Pnt& P1,
|
|
const gp_Pnt& P2,
|
|
const Select3D_TypeOfSensitivity aType):
|
|
Select3D_SensitivePoly(OwnerId,3),
|
|
mytype (aType)
|
|
{
|
|
((Select3D_Pnt*)mypolyg3d)[0] = P0;
|
|
((Select3D_Pnt*)mypolyg3d)[1] = P1;
|
|
((Select3D_Pnt*)mypolyg3d)[2] = P2;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Matches
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
Standard_Boolean Select3D_SensitiveTriangle::
|
|
Matches(const Standard_Real X,
|
|
const Standard_Real Y,
|
|
const Standard_Real aTol,
|
|
Standard_Real& DMin)
|
|
{
|
|
Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
|
|
if(Bnd_Box2d(mybox2d).IsOut(gp_Pnt2d(X,Y))) return Standard_False;
|
|
|
|
Standard_Integer Res;
|
|
switch (mytype)
|
|
{
|
|
case Select3D_TOS_BOUNDARY:
|
|
Res = Status(X,Y,aTol,DMin);
|
|
return Res== 1;
|
|
break;
|
|
case Select3D_TOS_INTERIOR:
|
|
Res = Status(X,Y,aTol,DMin);
|
|
return (Res==0 || Res == 1);
|
|
#ifndef DEB
|
|
default:
|
|
break;
|
|
#endif
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Matches
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
Standard_Boolean Select3D_SensitiveTriangle::
|
|
Matches (const Standard_Real XMin,
|
|
const Standard_Real YMin,
|
|
const Standard_Real XMax,
|
|
const Standard_Real YMax,
|
|
const Standard_Real aTol)
|
|
{
|
|
Bnd_Box2d B;
|
|
B.Update(Min(XMin,XMax)-aTol,
|
|
Min(YMin,YMax)-aTol,
|
|
Max(XMin,XMax)+aTol,
|
|
Max(YMin,YMax)+aTol);
|
|
for(Standard_Integer i=0;i<=2;i++)
|
|
{
|
|
if(B.IsOut(((Select3D_Pnt2d*)mypolyg2d)[i]))
|
|
return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Matches
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean Select3D_SensitiveTriangle::
|
|
Matches (const TColgp_Array1OfPnt2d& aPoly,
|
|
const Bnd_Box2d& aBox,
|
|
const Standard_Real aTol)
|
|
{
|
|
Standard_Real Umin,Vmin,Umax,Vmax;
|
|
aBox.Get(Umin,Vmin,Umax,Vmax);
|
|
Standard_Real Tolu,Tolv;
|
|
Tolu = 1e-7;
|
|
Tolv = 1e-7;
|
|
CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
|
|
|
|
for(Standard_Integer i=0;i<=2;i++)
|
|
{
|
|
Standard_Integer RES = aClassifier2d.SiDans(((Select3D_Pnt2d*)mypolyg2d)[i]);
|
|
if(RES!=1) return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Points3D
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
void Select3D_SensitiveTriangle::Points3D(gp_Pnt& P0,gp_Pnt& P1,gp_Pnt& P2) const
|
|
{
|
|
P0 = ((Select3D_Pnt*)mypolyg3d)[0];
|
|
P1 = ((Select3D_Pnt*)mypolyg3d)[1];
|
|
P2 = ((Select3D_Pnt*)mypolyg3d)[2];
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Center3D
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
gp_Pnt Select3D_SensitiveTriangle::Center3D() const
|
|
{
|
|
gp_XYZ CDG(((Select3D_Pnt*)mypolyg3d)[0]);
|
|
CDG += ((Select3D_Pnt*)mypolyg3d)[1];
|
|
CDG += ((Select3D_Pnt*)mypolyg3d)[2];
|
|
CDG /=3.;
|
|
return gp_Pnt(CDG);;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Center2D
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
gp_XY Select3D_SensitiveTriangle::Center2D() const
|
|
{
|
|
return (gp_XY(((Select3D_Pnt2d*)mypolyg2d)[0])+gp_XY(((Select3D_Pnt2d*)mypolyg2d)[1])
|
|
+gp_XY(((Select3D_Pnt2d*)mypolyg2d)[2]))/3.;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Status
|
|
//purpose : 0 = inside /1 = Boundary/ 2 = outside
|
|
//=======================================================================
|
|
|
|
Standard_Integer Select3D_SensitiveTriangle::Status(const Standard_Real X,
|
|
const Standard_Real Y,
|
|
const Standard_Real aTol,
|
|
Standard_Real& DMin) const
|
|
{
|
|
return Status(((Select3D_Pnt2d*)mypolyg2d)[0],((Select3D_Pnt2d*)mypolyg2d)[1],
|
|
((Select3D_Pnt2d*)mypolyg2d)[2],gp_XY(X,Y),aTol,DMin);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Status
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Integer Select3D_SensitiveTriangle::Status(const gp_XY& p0,
|
|
const gp_XY& p1,
|
|
const gp_XY& p2,
|
|
const gp_XY& TheP,
|
|
const Standard_Real aTol,
|
|
Standard_Real& DMin)
|
|
{
|
|
Bnd_Box2d B;
|
|
B.Update(p0.X(),p0.Y());B.Update(p1.X(),p1.Y());B.Update(p2.X(),p2.Y());
|
|
B.Enlarge(aTol);
|
|
if(B.IsOut(TheP)) return 2;
|
|
|
|
// the point is classified corresponding to demi-spaces limited
|
|
// by each side of the triangle (with tolerance)
|
|
gp_XY V01(p1);V01-=p0;
|
|
gp_XY V02(p2);V02-=p0;
|
|
gp_XY V12(p2);V12-=p1;
|
|
|
|
Standard_Real TolTol = aTol*aTol;
|
|
|
|
// check these particular cases...
|
|
// if one of vectors is almost null (2 points are mixed),
|
|
// leave at once (it is already in the bounding box, which is good...)
|
|
|
|
DMin = aTol;
|
|
|
|
if ( V01.SquareModulus() <= gp::Resolution() )
|
|
{
|
|
Standard_Real LV = V02.SquareModulus();
|
|
if ( LV <= gp::Resolution())
|
|
return 0; // 3 points are mixed, and TheP is in the bounding box B...
|
|
|
|
if ( S3D_Str_NearSegment (p0, p2, TheP, aTol, DMin) )
|
|
return 0;
|
|
return 2;
|
|
}
|
|
if ( V02.SquareModulus() <= gp::Resolution() )
|
|
{
|
|
if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
|
|
return 0;
|
|
return 2;
|
|
}
|
|
if ( V12.SquareModulus() <= gp::Resolution() )
|
|
{
|
|
if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
|
|
return 0;
|
|
return 2;
|
|
}
|
|
if ( V01.CrossMagnitude(V02) <= gp::Resolution() )
|
|
{
|
|
if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
|
|
return 0;
|
|
return 2;
|
|
}
|
|
|
|
// oriented normal to p0p1...
|
|
gp_Dir2d N (-V01.Y(), V01.X());
|
|
Standard_Boolean Neg = (N * V02 < 0.);
|
|
if ( Neg )
|
|
N.Reverse();
|
|
|
|
gp_XY Vec(TheP);
|
|
Vec -= p0;
|
|
|
|
Standard_Real aD1 = Vec * N.XY();
|
|
if ( aD1 < -aTol )
|
|
return 2;
|
|
|
|
// oriented normal to p1p2...
|
|
if(Neg)
|
|
N.SetCoord(p2.Y()-p1.Y(),p1.X()-p2.X());
|
|
else
|
|
N.SetCoord(p1.Y()-p2.Y(),p2.X()-p1.X());
|
|
|
|
Vec.SetCoord(TheP.X()-p1.X(),TheP.Y()-p1.Y());
|
|
Standard_Real aD2 = Vec * N.XY();
|
|
if ( aD2 < -aTol )
|
|
return 2; // outside
|
|
|
|
// oriented normal to p2p0...
|
|
// attention v20 (x0-x2) => N y2-y0 => -N y0-y2
|
|
// (y0-y2) x0-x2 x2-x0
|
|
if(Neg)
|
|
N.SetCoord(p0.Y()-p2.Y(),p2.X()-p0.X());
|
|
else
|
|
N.SetCoord(p2.Y()-p0.Y(),p0.X()-p2.X());
|
|
|
|
Vec.SetCoord(TheP.X()-p2.X(),TheP.Y()-p2.Y());
|
|
Standard_Real aD3 = Vec * N.XY();
|
|
if ( aD3 < -aTol )
|
|
return 2; // outside
|
|
|
|
// compute 2d distance to triangle
|
|
Standard_Real aD = Min (aD1, Min (aD2, aD3));
|
|
DMin = ( aD < 0 ? -aD : 0. );
|
|
return 0;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Dump
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Select3D_SensitiveTriangle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
|
|
{
|
|
// general information....
|
|
|
|
S<<"\tSensitiveTriangle 3D :\n";
|
|
if(HasLocation())
|
|
S<<"\t\tExisting Location"<<endl;
|
|
|
|
S<<"\t\t P0 [ "<<COORD(0,x)<<" , "<<COORD(0,y) <<" , "<<COORD(0,z)<<" ]"<<endl;
|
|
S<<"\t\t P1 [ "<<COORD(1,x)<<" , "<<COORD(1,y) <<" , "<<COORD(1,z)<<" ]"<<endl;
|
|
S<<"\t\t P2 [ "<<COORD(2,x)<<" , "<<COORD(2,y) <<" , "<<COORD(2,z)<<" ]"<<endl;
|
|
|
|
if(FullDump)
|
|
{
|
|
S<<"\t\tProjected Points"<<endl;
|
|
|
|
S<<"\t\t 0.[ "<<COORD2d(0,x)<<" , "<<COORD2d(0,y)<<" ]"<<endl;
|
|
S<<"\t\t 1.[ "<<COORD2d(1,x)<<" , "<<COORD2d(1,y)<<" ]"<<endl;
|
|
S<<"\t\t 2.[ "<<COORD2d(2,x)<<" , "<<COORD2d(2,y)<<" ]"<<endl;
|
|
// S<<"\t\t\tOwner:"<<myOwnerId<<endl;
|
|
Select3D_SensitiveEntity::DumpBox(S,mybox2d);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ComputeDepth
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Real Select3D_SensitiveTriangle::ComputeDepth(const gp_Lin& EyeLine) const
|
|
{
|
|
gp_Pnt P1 = ((Select3D_Pnt*)mypolyg3d)[0];
|
|
gp_Pnt P2 = ((Select3D_Pnt*)mypolyg3d)[1];
|
|
gp_Pnt P3 = ((Select3D_Pnt*)mypolyg3d)[2];
|
|
|
|
gp_Trsf TheTrsf ;
|
|
if(HasLocation())
|
|
TheTrsf = Location().Transformation();
|
|
|
|
if(TheTrsf.Form()!=gp_Identity)
|
|
{
|
|
P1.Transform(TheTrsf);
|
|
P2.Transform(TheTrsf);
|
|
P3.Transform(TheTrsf);
|
|
}
|
|
|
|
Standard_Real prof(Precision::Infinite());
|
|
// formula calculation of the point parameters on intersection
|
|
// t = (P1P2 ^P1P3)* OP1 / ((P1P2^P1P3)*Dir)
|
|
|
|
gp_Pnt Oye = EyeLine.Location(); // origin of the target line eye/point...
|
|
gp_Dir Dir = EyeLine.Direction();
|
|
|
|
gp_Vec P1P2 (P1,P2), P1P3(P1,P3);
|
|
P1P2.Normalize();
|
|
P1P3.Normalize();
|
|
|
|
gp_Vec oP1(Oye,P1);
|
|
Standard_Real val1 = oP1.DotCross(P1P2,P1P3);
|
|
Standard_Real val2 = Dir.DotCross(P1P2,P1P3);
|
|
|
|
if(Abs(val2)>Precision::Confusion())
|
|
prof =val1/val2;
|
|
|
|
if (prof==Precision::Infinite())
|
|
{
|
|
prof= ElCLib::Parameter(EyeLine,P1);
|
|
prof = Min (prof, ElCLib::Parameter(EyeLine,P2));
|
|
prof = Min (prof, ElCLib::Parameter(EyeLine,P3));
|
|
}
|
|
return prof;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: GetConnected
|
|
// Purpose :
|
|
//==================================================
|
|
|
|
Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::
|
|
GetConnected(const TopLoc_Location &theLocation)
|
|
{
|
|
// Create a copy of this
|
|
Handle(Select3D_SensitiveEntity) aNewEntity =
|
|
new Select3D_SensitiveTriangle(myOwnerId,
|
|
((Select3D_Pnt*)mypolyg3d)[0],
|
|
((Select3D_Pnt*)mypolyg3d)[1],
|
|
((Select3D_Pnt*)mypolyg3d)[2],
|
|
mytype);
|
|
|
|
if (HasLocation())
|
|
aNewEntity->SetLocation(Location());
|
|
|
|
aNewEntity->UpdateLocation(theLocation);
|
|
|
|
return aNewEntity;
|
|
} |