0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / DsgPrs / DsgPrs_EqualDistancePresentation.cxx
1 // Created on: 1998-01-27
2 // Created by: Julia GERASIMOVA
3 // Copyright (c) 1998-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
18 #include <DsgPrs.hxx>
19 #include <DsgPrs_EqualDistancePresentation.hxx>
20 #include <ElCLib.hxx>
21 #include <gce_MakeDir.hxx>
22 #include <Geom_Plane.hxx>
23 #include <gp_Circ.hxx>
24 #include <gp_Dir.hxx>
25 #include <gp_Pln.hxx>
26 #include <gp_Pnt.hxx>
27 #include <gp_Vec.hxx>
28 #include <Graphic3d_ArrayOfPolylines.hxx>
29 #include <Graphic3d_ArrayOfSegments.hxx>
30 #include <Graphic3d_Group.hxx>
31 #include <Precision.hxx>
32 #include <Prs3d_DimensionAspect.hxx>
33 #include <Prs3d_LineAspect.hxx>
34 #include <Prs3d_Presentation.hxx>
35 #include <Prs3d_Root.hxx>
36 #include <Prs3d_Text.hxx>
37 #include <TCollection_ExtendedString.hxx>
38
39 //=================================================================================
40 //function  : Add
41 //=================================================================================
42 void DsgPrs_EqualDistancePresentation::Add( const Handle( Prs3d_Presentation )& aPresentation,
43                                             const Handle( Prs3d_Drawer )& aDrawer,
44                                             const gp_Pnt& Point1,
45                                             const gp_Pnt& Point2,
46                                             const gp_Pnt& Point3,
47                                             const gp_Pnt& Point4,
48                                             const Handle( Geom_Plane )& Plane )
49 {
50   Handle( Prs3d_DimensionAspect ) LA = aDrawer->DimensionAspect();
51   Prs3d_Root::CurrentGroup( aPresentation )->SetPrimitivesAspect( LA->LineAspect()->Aspect() );
52
53   // Line between two middles
54   gp_Pnt Middle12( (Point1.XYZ() + Point2.XYZ()) * 0.5 ), Middle34( (Point3.XYZ() + Point4.XYZ()) * 0.5 );
55
56   Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2);
57   aPrims->AddVertex(Middle12);
58   aPrims->AddVertex(Middle34);
59   Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(aPrims);
60
61   // Add presentation of arrows (points)
62   gp_Dir aDir( 0, 0, 1 );
63   DsgPrs::ComputeSymbol(aPresentation, LA, Middle12, Middle34, aDir, aDir, DsgPrs_AS_BOTHPT );
64 // ota -- begin --  
65   // Two small lines in the middle of this line
66   gp_Pnt Middle( (Middle12.XYZ() + Middle34.XYZ()) * 0.5 ), aTextPos;
67   Standard_Real Dist = Middle12.Distance( Middle34 );
68   Standard_Real SmallDist;
69   gp_Dir LineDir, OrtDir;
70   gp_Vec LineVec, OrtVec;
71
72   if (Dist > Precision::Confusion())
73   {
74     SmallDist = Dist * 0.05; // 1/20.0 part
75     if (SmallDist <= Precision::Confusion())
76       SmallDist = Dist;
77     LineDir = gce_MakeDir( Middle12, Middle34 );
78     OrtDir  = Plane->Pln().Axis().Direction() ^ LineDir;
79     LineVec = gp_Vec( LineDir ) * SmallDist;
80     OrtVec  = gp_Vec( OrtDir ) * SmallDist;
81
82     aTextPos = Middle.Translated( OrtVec );
83   }
84   else
85   {
86     gp_Vec Vec1( Middle, Point1 );
87
88     if (Vec1.SquareMagnitude() > Precision::Confusion()*Precision::Confusion())
89         {
90           Standard_Real Angle = gp_Vec( Middle, Point1 ).Angle( gp_Vec( Middle, Point3 ) );
91           gp_Pnt MidPnt = Point1.Rotated( Plane->Pln().Axis(), Angle*0.5 );
92           OrtDir  = gce_MakeDir( Middle, MidPnt );
93           LineDir = OrtDir ^ Plane->Pln().Axis().Direction();
94           
95           Standard_Real Distance = Point1.Distance( Point2 );
96           SmallDist = Distance * 0.05; // 1/20.0
97           if (SmallDist <= Precision::Confusion())
98             SmallDist = Distance;
99           
100           OrtVec = gp_Vec( OrtDir ) * SmallDist;
101           LineVec = gp_Vec( LineDir ) * SmallDist;
102         }
103     else
104         {
105           SmallDist = 5.0;
106           OrtVec = gp_Vec( Plane->Pln().XAxis().Direction() ) * SmallDist;
107           LineVec = gp_Vec( Plane->Pln().YAxis().Direction() ) * SmallDist;
108         }
109     aTextPos =  Middle.Translated (OrtVec);
110   }
111
112   TCollection_ExtendedString aText("==");
113
114   //Draw the text
115   Prs3d_Text::Draw (Prs3d_Root::CurrentGroup (aPresentation),LA->TextAspect(), aText, aTextPos);
116 }
117
118
119 //==================================================================================
120 //function  : AddInterval
121 //purpose   : is used for presentation of interval between two lines or two points, 
122 //            or between one line and one point.
123 //==================================================================================
124  void DsgPrs_EqualDistancePresentation::AddInterval(const Handle(Prs3d_Presentation)& aPresentation,
125                                                     const Handle(Prs3d_Drawer)& aDrawer,
126                                                     const gp_Pnt& aPoint1,
127                                                     const gp_Pnt& aPoint2,
128                                                     const gp_Dir& aDirection,
129                                                     const gp_Pnt& aPosition,
130                                                     const DsgPrs_ArrowSide anArrowSide,
131                                                     gp_Pnt& aProj1,
132                                                     gp_Pnt& aProj2) 
133 {
134   const Handle(Prs3d_DimensionAspect) LA = aDrawer->DimensionAspect();
135   Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(LA->LineAspect()->Aspect());
136   
137   gp_Lin L1 (aPoint1,aDirection);
138   gp_Lin L2 (aPoint2,aDirection);
139   aProj1 = ElCLib::Value(ElCLib::Parameter(L1, aPosition),L1);
140   aProj2 = ElCLib::Value(ElCLib::Parameter(L2, aPosition),L2);
141
142   Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(4);
143   aPrims->AddVertex(aPoint1);
144   aPrims->AddVertex(aProj1);
145   aPrims->AddVertex(aProj2);
146   aPrims->AddVertex(aPoint2);
147   Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(aPrims);
148
149   //add arrows presentation
150   gp_Dir aDir(aProj2.XYZ() - aProj1.XYZ());
151   
152   DsgPrs::ComputeSymbol(aPresentation, LA, aProj1, aProj2, aDir.Reversed(), aDir, anArrowSide);
153 }
154
155
156 //========================================================================
157 // function : AddIntervalBetweenTwoArcs 
158 // purpose  : is used for presentation of interval between two arcs. One
159 //            of the arcs can have a zero radius (being a point really) 
160 //========================================================================
161  void 
162   DsgPrs_EqualDistancePresentation::AddIntervalBetweenTwoArcs(const Handle(Prs3d_Presentation)& aPresentation,
163                                                               const Handle(Prs3d_Drawer)& aDrawer,
164                                                               const gp_Circ& aCirc1,
165                                                               const gp_Circ& aCirc2,
166                                                               const gp_Pnt& aPoint1,
167                                                               const gp_Pnt& aPoint2,
168                                                               const gp_Pnt& aPoint3,
169                                                               const gp_Pnt& aPoint4,
170                                                               const DsgPrs_ArrowSide anArrowSide) 
171 {
172   const Handle(Prs3d_DimensionAspect) LA = aDrawer->DimensionAspect();
173   Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(LA->LineAspect()->Aspect());
174
175   Standard_Real aPar11, aPar12, aPar21, aPar22;
176   if(aCirc1.Radius() > Precision::Confusion()){
177     aPar11 = ElCLib::Parameter (aCirc1, aPoint1);
178     aPar12 = ElCLib::Parameter(aCirc1, aPoint2);
179   }
180   else {
181     aPar11 = M_PI;
182     aPar12 = M_PI;
183   }
184   if (aCirc2.Radius() > Precision::Confusion()){
185     aPar21 = ElCLib::Parameter(aCirc2, aPoint3 );
186     aPar22 = ElCLib::Parameter(aCirc2, aPoint4);
187   }
188   else {
189     aPar21 = M_PI;
190     aPar22 = M_PI;
191   }
192
193   Handle(Graphic3d_ArrayOfPrimitives) aPrims = new Graphic3d_ArrayOfSegments(2);
194   aPrims->AddVertex(aPoint2);
195   aPrims->AddVertex(aPoint4);
196   Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(aPrims);
197
198   Standard_Integer i, aNodeNb;
199   Standard_Real aDelta, aCurPar;
200   if(aPar12 < aPar11 ) aPar12 += 2.*M_PI;
201   if (Abs(aPar12 - aPar11) > Precision::Confusion())
202   {
203     aNodeNb = Standard_Integer(Max(Abs(aPar12 - aPar11)*50./M_PI + 0.5, 4.));
204     aDelta = (aPar12 - aPar11)/aNodeNb;
205     aCurPar= aPar11;
206
207     aPrims = new Graphic3d_ArrayOfPolylines(aNodeNb+1);
208     for (i = 1; i<= aNodeNb; aCurPar += aDelta, i++)
209       aPrims->AddVertex(ElCLib::Value( aCurPar, aCirc1));
210     aPrims->AddVertex(aPoint2);
211     Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(aPrims);
212   }
213   if (aPar22 < aPar21) aPar22 += 2.*M_PI;
214   if ( Abs(aPar22 - aPar21) > Precision::Confusion())
215   {
216     aNodeNb = Standard_Integer(Max(Abs(aPar22 - aPar21)*50./M_PI + 0.5, 4.));
217     aDelta = (aPar22 - aPar21)/aNodeNb;
218     aCurPar= aPar21;
219
220     aPrims = new Graphic3d_ArrayOfPolylines(aNodeNb+1);
221     for (i = 1; i<= aNodeNb; aCurPar += aDelta, i++)
222       aPrims->AddVertex(ElCLib::Value( aCurPar, aCirc2));
223     aPrims->AddVertex(aPoint4);
224     Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(aPrims);
225   }
226
227   //get the direction of interval
228   gp_Dir DirOfArrow;
229   if(aPoint4.Distance(aPoint2) > Precision::Confusion())
230   {
231     DirOfArrow.SetXYZ(aPoint4.XYZ() - aPoint2.XYZ());
232   }
233   else
234   {
235     //Let's take the radius direction
236     gp_Pnt aCenter = aCirc1.Location();
237     if(aPoint4.Distance(aCenter) < Precision::Confusion())
238       return;
239     DirOfArrow.SetXYZ(aPoint4.XYZ() - aCenter.XYZ());
240   }
241
242   // Add presentation of arrows
243   DsgPrs::ComputeSymbol( aPresentation, LA, aPoint2, aPoint4, DirOfArrow.Reversed(), DirOfArrow, anArrowSide );
244 }
245 //-- ota -- end