0024623: Visualization - improve selection mechanism
[occt.git] / src / AIS / AIS_ParallelRelation.cxx
1 // Created on: 1996-12-05
2 // Created by: Jean-Pierre COMBE/Odile Olivier
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <AIS_ParallelRelation.ixx>
18
19 #include <Standard_NotImplemented.hxx>
20 #include <Standard_DomainError.hxx>
21
22 #include <Precision.hxx>
23
24 #include <TCollection_AsciiString.hxx>
25 #include <TCollection_ExtendedString.hxx>
26
27 #include <DsgPrs_LengthPresentation.hxx>
28
29 #include <Prs3d_Drawer.hxx>
30 #include <Prs3d_ArrowAspect.hxx>
31 #include <Prs3d_DimensionAspect.hxx>
32
33 #include <AIS.hxx>
34
35 #include <SelectMgr_EntityOwner.hxx>
36 #include <SelectMgr_Selection.hxx>
37 #include <Select3D_SensitiveSegment.hxx>
38 #include <Select3D_SensitiveBox.hxx>
39
40 #include <TopoDS.hxx>
41 #include <TopExp_Explorer.hxx>
42 #include <BRep_Tool.hxx>
43 #include <BRepAdaptor_Surface.hxx>
44 #include <BRepAdaptor_Curve.hxx>
45
46 #include <gp_Lin.hxx>
47 #include <gp_Pnt.hxx>
48 #include <ElCLib.hxx>
49 #include <gp_Pln.hxx>
50 #include <gp_Dir.hxx>
51 #include <gp_Ax1.hxx>
52 #include <gp_Ax2.hxx>
53
54 #include <gce_MakeLin.hxx>
55
56 #include <Geom_Plane.hxx>
57 #include <Geom_Line.hxx>
58 #include <Geom_Ellipse.hxx>
59
60 //=======================================================================
61 //function : Constructor
62 //purpose  : 
63 //=======================================================================
64 AIS_ParallelRelation::AIS_ParallelRelation(const TopoDS_Shape& aFShape, 
65                                            const TopoDS_Shape& aSShape, 
66                                            const Handle(Geom_Plane)& aPlane)
67 {
68   myFShape = aFShape;
69   mySShape = aSShape;
70   myPlane = aPlane;
71   myAutomaticPosition = Standard_True;
72   myArrowSize = 0.01;
73   mySymbolPrs = DsgPrs_AS_BOTHAR;
74 }
75
76 //=======================================================================
77 //function : Constructor
78 //purpose  : 
79 //=======================================================================
80 AIS_ParallelRelation::AIS_ParallelRelation(const TopoDS_Shape& aFShape, 
81                                            const TopoDS_Shape& aSShape, 
82                                            const Handle(Geom_Plane)& aPlane, 
83                                            const gp_Pnt& aPosition,
84                                            const DsgPrs_ArrowSide aSymbolPrs, 
85                                            const Standard_Real anArrowSize)
86 {
87   myFShape = aFShape;
88   mySShape = aSShape;
89   myPlane = aPlane;
90   myAutomaticPosition = Standard_False;
91   SetArrowSize( anArrowSize );
92   myPosition = aPosition;
93   mySymbolPrs = aSymbolPrs;
94 }
95
96 //=======================================================================
97 //function : Compute
98 //purpose  : 
99 //=======================================================================
100 void AIS_ParallelRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
101                                    const Handle(Prs3d_Presentation)& aPresentation, 
102                                    const Standard_Integer)
103 {
104   aPresentation->Clear();
105
106   switch (myFShape.ShapeType())
107     {
108     case TopAbs_FACE :
109       {
110         // cas longueur entre deux faces
111         ComputeTwoFacesParallel(aPresentation);
112       }
113       break;
114     case TopAbs_EDGE :
115       {
116         // cas longueur entre deux edges
117         ComputeTwoEdgesParallel(aPresentation);
118       }
119       break;
120     default:
121       break;
122     }
123 }
124
125 //=======================================================================
126 //function : Compute
127 //purpose  : to avoid warning
128 //=======================================================================
129 void AIS_ParallelRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
130                                    const Handle(Prs3d_Presentation)& aPresentation)
131 {
132 // Standard_NotImplemented::Raise("AIS_ParallelRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
133   PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
134 }
135
136 void AIS_ParallelRelation::Compute(const Handle(Prs3d_Projector)& aProjector, const Handle(Geom_Transformation)& aTransformation, const Handle(Prs3d_Presentation)& aPresentation)
137 {
138 // Standard_NotImplemented::Raise("AIS_ParallelRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
139   PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
140 }
141
142 //=======================================================================
143 //function : ComputeSelection
144 //purpose  : 
145 //=======================================================================
146 void AIS_ParallelRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
147                                             const Standard_Integer)
148 {
149   gp_Lin L1 (myFAttach,myDirAttach);
150   gp_Lin L2 (mySAttach,myDirAttach);
151   gp_Pnt Proj1 = ElCLib::Value(ElCLib::Parameter(L1,myPosition),L1);
152   gp_Pnt Proj2 = ElCLib::Value(ElCLib::Parameter(L2,myPosition),L2);
153   
154   gp_Lin L3;
155   Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
156
157   if (!Proj1.IsEqual(Proj2,Precision::Confusion()))
158     {
159       L3 = gce_MakeLin(Proj1,Proj2);
160     }
161   else
162     {
163       L3 = gce_MakeLin(Proj1,myDirAttach);
164       Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
165       Handle(Select3D_SensitiveBox) box =
166         new Select3D_SensitiveBox(own,
167                                   myPosition.X(),
168                                   myPosition.Y(),
169                                   myPosition.Z(),
170                                   myPosition.X()+size,
171                                   myPosition.Y()+size,
172                                   myPosition.Z()+size);
173       aSelection->Add(box);
174     }
175   Standard_Real parmin,parmax,parcur;
176   parmin = ElCLib::Parameter(L3,Proj1);
177   parmax = parmin;
178   
179   parcur = ElCLib::Parameter(L3,Proj2);
180   parmin = Min(parmin,parcur);
181   parmax = Max(parmax,parcur);
182   
183   parcur = ElCLib::Parameter(L3,myPosition);
184   parmin = Min(parmin,parcur);
185   parmax = Max(parmax,parcur);
186   
187   gp_Pnt PointMin = ElCLib::Value(parmin,L3);
188   gp_Pnt PointMax = ElCLib::Value(parmax,L3);
189
190   Handle(Select3D_SensitiveSegment) seg;
191   
192   if (!PointMin.IsEqual(PointMax,Precision::Confusion()))
193     {
194       seg = new Select3D_SensitiveSegment(own,
195                                           PointMin,
196                                           PointMax);
197       aSelection->Add(seg);
198     }
199   if (!myFAttach.IsEqual(Proj1,Precision::Confusion()))
200     {
201       seg = new Select3D_SensitiveSegment(own, myFAttach, Proj1);
202       aSelection->Add(seg);
203     }
204   if (!mySAttach.IsEqual(Proj2,Precision::Confusion()))
205     {
206       seg = new Select3D_SensitiveSegment(own, mySAttach, Proj2);
207       aSelection->Add(seg);
208     }
209 }
210
211 //=======================================================================
212 //function : ComputeTwoFacesParallel
213 //purpose  : 
214 //=======================================================================
215 void AIS_ParallelRelation::ComputeTwoFacesParallel(const Handle(Prs3d_Presentation)&)
216 {
217   Standard_NotImplemented::Raise("AIS_ParallelRelation::ComputeTwoFacesParallel not implemented");
218 }
219
220 //=======================================================================
221 //function : ComputeTwoEdgesParallel
222 //purpose  : 
223 //=======================================================================
224 void AIS_ParallelRelation::ComputeTwoEdgesParallel(const Handle(Prs3d_Presentation)& aPresentation)
225 {
226   TopoDS_Edge E1 = TopoDS::Edge(myFShape);
227   TopoDS_Edge E2 = TopoDS::Edge(mySShape);
228
229   gp_Pnt ptat11,ptat12,ptat21,ptat22;//,pint3d;
230   Handle(Geom_Curve) geom1,geom2;
231   Standard_Boolean isInfinite1,isInfinite2;
232   Handle(Geom_Curve) extCurv;
233   if (!AIS::ComputeGeometry(E1,E2,myExtShape,
234                             geom1,geom2,
235                             ptat11,ptat12,ptat21,ptat22,
236                             extCurv,
237                             isInfinite1,isInfinite2,
238                             myPlane))
239     {
240       return;
241     }
242
243   aPresentation->SetInfiniteState((isInfinite1 || isInfinite2) && (myExtShape != 0));
244
245   gp_Lin l1;
246   gp_Lin l2;
247   Standard_Boolean isEl1 = Standard_False, isEl2 = Standard_False;
248
249   if (geom1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
250     {
251       const Handle(Geom_Ellipse)& geom_el1 = (Handle(Geom_Ellipse)&) geom1;
252       // construct lines through focuses
253       gp_Ax1 elAx = geom_el1->XAxis();
254       l1 = gp_Lin(elAx);
255       Standard_Real focex = geom_el1->MajorRadius() - geom_el1->Focal()/2.0;
256       gp_Vec transvec = gp_Vec(elAx.Direction())*focex;
257       ptat11 = geom_el1->Focus1().Translated(transvec);
258       ptat12 = geom_el1->Focus2().Translated(-transvec);
259       isEl1 = Standard_True;
260     }
261   else if (geom1->IsInstance(STANDARD_TYPE(Geom_Line)))
262     {
263       const Handle(Geom_Line)& geom_lin1 = (Handle(Geom_Line)&) geom1;
264       l1 = geom_lin1->Lin();
265     }
266   else return;
267
268   if (geom2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
269     {
270       const Handle(Geom_Ellipse)& geom_el2 = (Handle(Geom_Ellipse)&) geom2;
271       // construct lines through focuses
272       gp_Ax1 elAx = geom_el2->XAxis();
273       l2 = gp_Lin(elAx);
274       Standard_Real focex = geom_el2->MajorRadius() - geom_el2->Focal()/2.0;
275       gp_Vec transvec = gp_Vec(elAx.Direction())*focex;
276       ptat21 = geom_el2->Focus1().Translated(transvec);
277       ptat22 = geom_el2->Focus2().Translated(-transvec);
278       isEl2 = Standard_True;
279     }
280   else if (geom2->IsInstance(STANDARD_TYPE(Geom_Line)))
281     {
282       const Handle(Geom_Line)& geom_lin2 = (Handle(Geom_Line)&) geom2;
283       l2 = geom_lin2->Lin();
284     }
285   else return;
286
287   const Handle(Geom_Line)& geom_lin1 = new Geom_Line(l1);
288   const Handle(Geom_Line)& geom_lin2 = new Geom_Line(l2);
289
290   myDirAttach = l1.Direction();
291   // size
292   if( !myArrowSizeIsDefined ) {
293     Standard_Real arrSize1 (myArrowSize), arrSize2 (myArrowSize);
294     if (!isInfinite1) arrSize1 = ptat11.Distance(ptat12)/50.;
295     if (!isInfinite2) arrSize2 = ptat21.Distance(ptat22)/50.;
296     myArrowSize = Max(myArrowSize,Max(arrSize1,arrSize2));
297 //  myArrowSize = Min(myArrowSize,Min(arrSize1,arrSize2));
298   }
299
300   if ( myAutomaticPosition )
301     {    
302       gp_Pnt curpos;
303       if ( !isInfinite1 )
304         {
305           gp_Pnt p2 = ElCLib::Value(ElCLib::Parameter(l2,ptat11),l2);
306           curpos.SetXYZ((ptat11.XYZ() + p2.XYZ())/2.);
307         }
308       else if ( !isInfinite2 )
309         {
310           gp_Pnt p2 = ElCLib::Value(ElCLib::Parameter(l1,ptat21),l1);
311           curpos.SetXYZ((ptat21.XYZ()+p2.XYZ())/2.);
312         }
313       else
314         {
315           curpos.SetXYZ((l1.Location().XYZ()+l2.Location().XYZ())/2.);
316         }
317       // offset pour eviter confusion Edge et Dimension
318       gp_Vec offset (myDirAttach);
319       offset = offset*myArrowSize*(-10.);
320       curpos.Translate(offset);
321       myPosition = curpos;
322     }
323
324   // recherche points attache
325   if (!isInfinite1)
326     {
327       if ( isEl1 )
328         {
329           if (myPosition.Distance(ptat11) < myPosition.Distance(ptat12)) myFAttach = ptat12;
330           else myFAttach = ptat11;
331         }
332       else
333         {
334           if (myPosition.Distance(ptat11) > myPosition.Distance(ptat12)) myFAttach = ptat12;
335           else myFAttach = ptat11;
336         }
337     }
338   else
339     {
340       myFAttach = ElCLib::Value(ElCLib::Parameter(l1,myPosition),l1);
341     }
342   
343   if (!isInfinite2)
344     {
345       if ( isEl2 )
346         {
347           if (myPosition.Distance(ptat21) < myPosition.Distance(ptat22)) mySAttach = ptat22;
348           else mySAttach = ptat21;
349         }
350       else
351         {
352           if (myPosition.Distance(ptat21) > myPosition.Distance(ptat22)) mySAttach = ptat22;
353           else mySAttach = ptat21;
354         }
355     }
356   else
357     {
358       mySAttach = ElCLib::Value(ElCLib::Parameter(l2,myPosition),l2);
359     }
360   TCollection_ExtendedString aText (" //");
361   
362   if (l1.Distance(l2) <= Precision::Confusion())
363     {
364       myArrowSize = 0.;
365     }
366   Handle(Prs3d_DimensionAspect) la = myDrawer->DimensionAspect();
367   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
368   arr->SetLength(myArrowSize);
369   arr = la->ArrowAspect();
370   arr->SetLength(myArrowSize);
371   if ( myExtShape == 1)
372     mySymbolPrs = DsgPrs_AS_FIRSTPT_LASTAR;
373   else if ( myExtShape == 2)
374     mySymbolPrs = DsgPrs_AS_FIRSTAR_LASTPT;
375
376   DsgPrs_LengthPresentation::Add(aPresentation,
377                                  myDrawer,
378                                  aText,
379                                  myFAttach,
380                                  mySAttach,
381                                  myDirAttach,
382                                  myPosition,
383                                  mySymbolPrs);
384   if ( (myExtShape != 0) &&  !extCurv.IsNull())
385     {
386       gp_Pnt pf, pl;
387       if ( myExtShape == 1 )
388         {
389           if (!isInfinite1)
390             {
391               pf = ptat11; 
392               pl = ptat12;
393             }
394           ComputeProjEdgePresentation(aPresentation,E1,geom_lin1,pf,pl);
395         }
396       else
397         {
398           if (!isInfinite2)
399             {
400               pf = ptat21; 
401               pl = ptat22;
402             }
403           ComputeProjEdgePresentation(aPresentation,E2,geom_lin2,pf,pl);
404         }
405     }
406 }