1 // Copyright: Matra-Datavision 1995
2 // File: Select3D_SensitiveSegment.cxx
3 // Created: Wed Jan 25 11:27:54 1995
8 #include <Select3D_SensitiveSegment.ixx>
9 #include <SelectBasics_BasicTool.hxx>
11 #include <gp_Vec2d.hxx>
12 #include <Bnd_Box2d.hxx>
13 #include <gp_Pnt2d.hxx>
14 #include <gp_Dir2d.hxx>
15 #include <gp_Lin2d.hxx>
17 #include <Extrema_ExtElC.hxx>
18 #include <Extrema_POnCurv.hxx>
19 #include <TColgp_Array1OfPnt2d.hxx>
20 #include <Precision.hxx>
21 #include <SelectBasics_ListIteratorOfListOfBox2d.hxx>
23 #include <CSLib_Class2d.hxx>
25 //=====================================================
27 // Purpose :Constructor
28 //=====================================================
31 Select3D_SensitiveSegment::
32 Select3D_SensitiveSegment(const Handle(SelectBasics_EntityOwner)& OwnerId,
35 const Standard_Integer MaxRect):
36 Select3D_SensitiveEntity(OwnerId),
43 //=====================================================
46 //=====================================================
47 void Select3D_SensitiveSegment
48 ::Project(const Select3D_Projector& aProj)
50 Select3D_SensitiveEntity::Project(aProj); // to set the field last proj...
51 gp_Pnt2d aPoint2dStart;
55 gp_Pnt aStart(mystart.x, mystart.y, mystart.z);
56 gp_Pnt aEnd(myend.x, myend.y, myend.z);
57 aProj.Project(aStart.Transformed(Location().Transformation()),aPoint2dStart);
58 aProj.Project(aEnd.Transformed(Location().Transformation()),aPoint2dEnd);
61 aProj.Project(mystart,aPoint2dStart);
62 aProj.Project(myend,aPoint2dEnd);
64 myprojstart = aPoint2dStart;
65 myprojend = aPoint2dEnd;
68 //=====================================================
71 //=====================================================
72 void Select3D_SensitiveSegment
73 ::Areas(SelectBasics_ListOfBox2d& theareas)
75 // gp_Dir2d dy (0.,1.);
76 gp_Pnt2d aPStart(myprojstart.x,myprojstart.y);
77 if(aPStart.Distance(myprojend)<=Precision::Confusion()){
79 curbox.Set(myprojstart);
80 theareas.Append(curbox);
83 gp_Vec2d MyVec(myprojstart,myprojend);//,VAxx(gp_Dir2d(0.,1.));
84 Standard_Real theangle = Abs(gp_Dir2d(0.,1.).Angle(gp_Vec2d(myprojstart,myprojend)));
85 if(theangle>=PI/2.) theangle-=PI/2;
86 if(theangle>=PI/12. && theangle <=5*PI/12.)
88 TColgp_Array1OfPnt2d BoxPoint (1,mymaxrect+1);
89 BoxPoint (1) = myprojstart;
90 BoxPoint(mymaxrect+1)=myprojend;
91 gp_Vec2d Vtr = MyVec/mymaxrect;
92 // for (Standard_Integer i=2;i<=mymaxrect;i++)
94 for ( i=2;i<=mymaxrect;i++)
95 {BoxPoint (i) = BoxPoint (i-1).Translated(Vtr);}
96 for (i=2;i<=mymaxrect+1;i++)
98 curbox.Set(BoxPoint(i-1));
99 curbox.Add(BoxPoint(i));
100 theareas.Append(curbox);
106 curbox.Set(myprojstart);
107 curbox.Add(myprojend);
108 theareas.Append(curbox);
113 //=====================================================
114 // Function : Matches
116 //=====================================================
117 Standard_Boolean Select3D_SensitiveSegment
118 ::Matches(const Standard_Real X,
119 const Standard_Real Y,
120 const Standard_Real aTol,
123 gp_Pnt2d aPStart(myprojstart.x,myprojstart.y);
124 gp_Pnt2d aPEnd(myprojend.x,myprojend.y);
125 if ( ! SelectBasics_BasicTool::MatchSegment (aPStart, aPEnd, X, Y, aTol, DMin) )
126 return Standard_False;
127 Select3D_SensitiveEntity::Matches (X, Y, aTol, DMin); // to compute depth
128 return Standard_True;
131 Standard_Boolean Select3D_SensitiveSegment::
132 Matches (const Standard_Real XMin,
133 const Standard_Real YMin,
134 const Standard_Real XMax,
135 const Standard_Real YMax,
136 const Standard_Real aTol)
139 BoundBox.Update(XMin-aTol,YMin-aTol,XMax+aTol,YMax+aTol);
140 if(BoundBox.IsOut(myprojstart)) return Standard_False;
141 if( BoundBox.IsOut(myprojend)) return Standard_False;
142 return Standard_True;
146 //=======================================================================
149 //=======================================================================
151 Standard_Boolean Select3D_SensitiveSegment::
152 Matches (const TColgp_Array1OfPnt2d& aPoly,
153 const Bnd_Box2d& aBox,
154 const Standard_Real aTol)
156 Standard_Real Umin,Vmin,Umax,Vmax;
157 aBox.Get(Umin,Vmin,Umax,Vmax);
158 Standard_Real Tolu,Tolv;
161 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
163 Standard_Integer RES = aClassifier2d.SiDans(myprojstart);
164 if (RES!=1) return Standard_False;
166 RES = aClassifier2d.SiDans(myprojend);
167 if (RES!=1) return Standard_False;
169 return Standard_True;
173 //=======================================================================
174 //function : GetConnected
176 //=======================================================================
177 Handle(Select3D_SensitiveEntity) Select3D_SensitiveSegment::GetConnected(const TopLoc_Location& aLoc)
179 Handle(Select3D_SensitiveSegment) NiouEnt = new Select3D_SensitiveSegment(myOwnerId,mystart,myend,mymaxrect);
180 if(HasLocation()) NiouEnt->SetLocation(Location());
181 NiouEnt->UpdateLocation(aLoc);
185 //=======================================================================
188 //=======================================================================
190 void Select3D_SensitiveSegment::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
192 S<<"\tSensitivePoint 3D :"<<endl;
194 S<<"\t\tExisting Location"<<endl;
195 S<<"\t\t P1 [ "<<mystart.x<<" , "<<mystart.y <<" , "<<mystart.z <<" ]"<<endl;
196 S<<"\t\t P2 [ "<<myend.x<<" , "<<myend.y <<" , "<<myend.z <<" ]"<<endl;
197 S<<"\t\t maxrect ="<<mymaxrect<<endl;
200 //=======================================================================
201 //function : ComputeDepth
203 //=======================================================================
205 Standard_Real Select3D_SensitiveSegment::ComputeDepth(const gp_Lin& EyeLine) const
207 gp_Pnt aP0 = mystart;
210 // if segment is degenerated (zero length), just use depth of the end
211 gp_XYZ aV = aP1.XYZ() - aP0.XYZ();
212 Standard_Real aNorm = aV.Modulus();
213 if ( aNorm <= gp::Resolution() )
214 return ElCLib::Parameter (EyeLine, aP0);
216 // else compute point on segment closest to the line
217 gp_Lin aLine (aP0, aV);
218 Extrema_ExtElC aTool (aLine, EyeLine, Precision::Angular());
219 if ( aTool.IsDone() && ! aTool.IsParallel() )
221 for (Standard_Integer i=1; i <= aTool.NbExt(); i++)
223 Extrema_POnCurv POL1, POL2;
224 aTool.Points (i, POL1, POL2);
225 // use point found by extrema only if it is inside segment
226 if ( POL1.Parameter() > 0. && POL1.Parameter() < aNorm )
227 return ElCLib::Parameter (EyeLine, POL1.Value());
231 // if extrema failed or lines are parallel, return closest of the segment ends
232 return Min (ElCLib::Parameter (EyeLine, aP0),
233 ElCLib::Parameter (EyeLine, aP1));