77ad2e8b3ca2889b1db9be780fbe5aeb20b1a3d4
[occt.git] / src / V3d / V3d_Trihedron.cxx
1 // Created on: 2016-10-11
2 // Created by: Ilya SEVRIKOV
3 // Copyright (c) 2016 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <V3d_Trihedron.hxx>
17
18 #include <gp_Ax3.hxx>
19 #include <Graphic3d_ArrayOfPolylines.hxx>
20 #include <Graphic3d_ArrayOfSegments.hxx>
21 #include <Graphic3d_ArrayOfTriangles.hxx>
22 #include <Graphic3d_Camera.hxx>
23 #include <Graphic3d_TransformPers.hxx>
24 #include <Prs3d.hxx>
25 #include <Prs3d_LineAspect.hxx>
26 #include <Prs3d_ShadingAspect.hxx>
27 #include <Prs3d_Text.hxx>
28 #include <Prs3d_TextAspect.hxx>
29 #include <StdPrs_ToolCylinder.hxx>
30 #include <StdPrs_ToolDisk.hxx>
31 #include <StdPrs_ToolSphere.hxx>
32 #include <V3d_View.hxx>
33
34 IMPLEMENT_STANDARD_RTTIEXT (V3d_Trihedron, Standard_Transient)
35
36 namespace
37 {
38   //! Compensates difference between old implementation (without transform persistence) and current implementation.
39   static const Standard_Real THE_INTERNAL_SCALE_FACTOR = 500.0;
40
41   static const Standard_ShortReal THE_CYLINDER_LENGTH      = 0.75f;
42   static const Standard_Integer   THE_CIRCLE_SERMENTS_NB   = 24;
43   static const Standard_Real      THE_CIRCLE_SEGMENT_ANGLE = 2.0 * M_PI / THE_CIRCLE_SERMENTS_NB;
44 }
45
46 //! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
47 class V3d_Trihedron::TrihedronStructure : public Graphic3d_Structure
48 {
49 public:
50   //! Main constructor.
51   TrihedronStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_Trihedron* theTrihedron)
52   : Graphic3d_Structure (theManager), myTrihedron (theTrihedron) {}
53
54   //! Override method to redirect to V3d_Trihedron.
55   virtual void Compute() Standard_OVERRIDE { myTrihedron->compute(); }
56
57 private:
58   V3d_Trihedron* myTrihedron;
59 };
60
61 // ============================================================================
62 // function : V3d_Trihedron
63 // purpose  :
64 // ============================================================================
65 V3d_Trihedron::V3d_Trihedron()
66 : myScale      (1.0),
67   myRatio      (0.8),
68   myDiameter   (0.05),
69   myNbFacettes (12),
70   myIsWireframe(Standard_False),
71   myToCompute  (Standard_True)
72 {
73   myTransformPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
74   SetPosition (Aspect_TOTP_LEFT_LOWER);
75
76   // Set material.
77   Graphic3d_MaterialAspect aShadingMaterial;
78   aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
79   aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
80
81   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
82   {
83     myArrowShadingAspects[anIt] = new Prs3d_ShadingAspect();
84     myArrowLineAspects[anIt]    = new Prs3d_LineAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0);
85
86     // mark texture map ON to actually disable environment map
87     myArrowShadingAspects[anIt]->Aspect()->SetTextureMapOn();
88     myArrowShadingAspects[anIt]->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
89     myArrowShadingAspects[anIt]->SetMaterial (aShadingMaterial);
90   }
91   myArrowShadingAspects[0]->SetColor (Quantity_NOC_RED);
92   myArrowLineAspects   [0]->SetColor (Quantity_NOC_RED);
93   myArrowShadingAspects[1]->SetColor (Quantity_NOC_GREEN);
94   myArrowLineAspects   [1]->SetColor (Quantity_NOC_GREEN);
95   myArrowShadingAspects[2]->SetColor (Quantity_NOC_BLUE1);
96   myArrowLineAspects   [2]->SetColor (Quantity_NOC_BLUE1);
97
98   mySphereShadingAspect = new Prs3d_ShadingAspect();
99   mySphereLineAspect    = new Prs3d_LineAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0);
100
101   // mark texture map ON to actually disable environment map
102   mySphereShadingAspect->Aspect()->SetTextureMapOn();
103   mySphereShadingAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
104   mySphereShadingAspect->SetMaterial (aShadingMaterial);
105   mySphereShadingAspect->SetColor (Quantity_NOC_WHITE);
106
107   myTextAspect = new Prs3d_TextAspect();
108   myTextAspect->SetFont ("Courier");
109   myTextAspect->SetHeight (16);
110   myTextAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT);
111   myTextAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
112 }
113
114 // ============================================================================
115 // function : SetLabelsColor
116 // purpose  :
117 // ============================================================================
118 void V3d_Trihedron::SetLabelsColor (const Quantity_Color& theColor)
119 {
120   myTextAspect->SetColor (theColor);
121 }
122
123 // ============================================================================
124 // function : SetArrowsColor
125 // purpose  :
126 // ============================================================================
127 void V3d_Trihedron::SetArrowsColor (const Quantity_Color& theXColor,
128                                     const Quantity_Color& theYColor,
129                                     const Quantity_Color& theZColor)
130 {
131   const Quantity_Color aColors[3] = { theXColor, theYColor, theZColor };
132   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
133   {
134     myArrowShadingAspects[anIt]->SetColor (aColors[anIt]);
135     myArrowLineAspects   [anIt]->SetColor (aColors[anIt]);
136   }
137 }
138
139 // ============================================================================
140 // function : SetScale
141 // purpose  :
142 // ============================================================================
143 void V3d_Trihedron::SetScale (const Standard_Real theScale)
144 {
145   if (Abs (myScale - theScale) > Precision::Confusion())
146   {
147     invalidate();
148   }
149   myScale = theScale;
150 }
151
152 // =======================================================================
153 // function : SetSizeRatio
154 // purpose  :
155 // =======================================================================
156 void V3d_Trihedron::SetSizeRatio (const Standard_Real theRatio)
157 {
158   if (Abs (myRatio - theRatio) > Precision::Confusion())
159   {
160     invalidate();
161   }
162   myRatio = theRatio;
163 }
164
165 // =======================================================================
166 // function : SetArrowDiameter
167 // purpose  :
168 // =======================================================================
169 void V3d_Trihedron::SetArrowDiameter (const Standard_Real theDiam)
170 {
171   if (Abs (myDiameter - theDiam) > Precision::Confusion())
172   {
173     invalidate();
174   }
175   myDiameter = theDiam;
176 }
177
178 // =======================================================================
179 // function : SetNbFacets
180 // purpose  :
181 // =======================================================================
182 void V3d_Trihedron::SetNbFacets (const Standard_Integer theNbFacets)
183 {
184   if (Abs (myNbFacettes - theNbFacets) > 0)
185   {
186     invalidate();
187   }
188   myNbFacettes = theNbFacets;
189 }
190
191 // ============================================================================
192 // function : Display
193 // purpose  :
194 // ============================================================================
195 void V3d_Trihedron::Display (const V3d_View& theView)
196 {
197   if (myStructure.IsNull())
198   {
199     myStructure = new TrihedronStructure (theView.Viewer()->StructureManager(), this);
200     myStructure->SetTransformPersistence (myTransformPers);
201     myStructure->SetZLayer (Graphic3d_ZLayerId_Topmost);
202     myStructure->SetDisplayPriority (9);
203     myStructure->SetInfiniteState (Standard_True);
204     myStructure->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
205     myStructure->CStructure()->ViewAffinity->SetVisible (Standard_False);
206     myStructure->CStructure()->ViewAffinity->SetVisible (theView.View()->Identification(), true);
207   }
208   if (myToCompute)
209   {
210     compute();
211   }
212
213   myStructure->Display();
214 }
215
216 // ============================================================================
217 // function : Erase
218 // purpose  :
219 // ============================================================================
220 void V3d_Trihedron::Erase()
221 {
222   if (!myStructure.IsNull())
223   {
224     myStructure->Erase();
225     myStructure.Nullify();
226   }
227 }
228
229 // ============================================================================
230 // function : SetPosition
231 // purpose  :
232 // ============================================================================
233 void V3d_Trihedron::SetPosition (const Aspect_TypeOfTriedronPosition thePosition)
234 {
235   Graphic3d_Vec2i anOffset (0, 0);
236   if ((thePosition & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
237   {
238     anOffset.x() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
239   }
240   if ((thePosition & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
241   {
242     anOffset.y() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
243   }
244
245   myTransformPers->SetCorner2d (thePosition);
246   myTransformPers->SetOffset2d (anOffset);
247 }
248
249 // ============================================================================
250 // function : compute
251 // purpose  :
252 // ============================================================================
253 void V3d_Trihedron::compute()
254 {
255   myStructure->GraphicClear (Standard_False);
256
257   // Create trihedron.
258   const Standard_Real aScale           = myScale * myRatio * THE_INTERNAL_SCALE_FACTOR;
259   const Standard_Real aCylinderLength  = aScale * THE_CYLINDER_LENGTH;
260   const Standard_Real aCylinderDiametr = aScale * myDiameter;
261   const Standard_Real aConeDiametr     = myIsWireframe ? aCylinderDiametr : (aCylinderDiametr * 2.0);
262   const Standard_Real aConeLength      = aScale * (1.0 - THE_CYLINDER_LENGTH);
263   const Standard_Real aSphereRadius    = aCylinderDiametr * 2.0;
264   const Standard_Real aRayon           = aScale / 30.0;
265   {
266     Handle(Graphic3d_Group) aSphereGroup = myStructure->NewGroup();
267
268     // Display origin.
269     if (myIsWireframe)
270     {
271       Handle(Graphic3d_ArrayOfPolylines) anCircleArray = new Graphic3d_ArrayOfPolylines (THE_CIRCLE_SERMENTS_NB + 2);
272       for (Standard_Integer anIt = THE_CIRCLE_SERMENTS_NB; anIt >= 0; --anIt)
273       {
274         anCircleArray->AddVertex (aRayon * Sin (anIt * THE_CIRCLE_SEGMENT_ANGLE),
275                                   aRayon * Cos (anIt * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
276       }
277       anCircleArray->AddVertex (aRayon * Sin (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE),
278                                 aRayon * Cos (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
279
280       aSphereGroup->SetGroupPrimitivesAspect (mySphereLineAspect->Aspect());
281       aSphereGroup->AddPrimitiveArray (anCircleArray);
282     }
283     else
284     {
285       gp_Trsf aSphereTransform;
286       aSphereGroup->SetGroupPrimitivesAspect (mySphereShadingAspect->Aspect());
287       aSphereGroup->AddPrimitiveArray (StdPrs_ToolSphere::Create (aSphereRadius, myNbFacettes, myNbFacettes, aSphereTransform));
288     }
289   }
290
291   // Display axes.
292   {
293     const gp_Ax1 anAxes[3] = { gp::OX(), gp::OY(), gp::OZ() };
294     for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
295     {
296       Handle(Graphic3d_Group) anAxisGroup = myStructure->NewGroup();
297       anAxisGroup->SetGroupPrimitivesAspect (myArrowShadingAspects[anIter]->Aspect());
298
299       gp_Ax1 aPosition (anAxes[anIter]);
300
301       // Create a tube.
302       if (myIsWireframe)
303       {
304         Handle(Graphic3d_ArrayOfPrimitives) anArray = new Graphic3d_ArrayOfSegments (2);
305         anArray->AddVertex (0.0f, 0.0f, 0.0f);
306         anArray->AddVertex (anAxes[anIter].Direction().XYZ() * aCylinderLength);
307
308         anAxisGroup->SetGroupPrimitivesAspect (myArrowLineAspects[anIter]->Aspect());
309         anAxisGroup->AddPrimitiveArray (anArray);
310       }
311       else
312       {
313         gp_Ax3  aSystem (aPosition.Location(), aPosition.Direction());
314         gp_Trsf aTrsf;
315         aTrsf.SetTransformation (aSystem, gp_Ax3());
316
317         anAxisGroup->AddPrimitiveArray (StdPrs_ToolCylinder::Create (aCylinderDiametr, aCylinderDiametr, aCylinderLength, myNbFacettes, 1, aTrsf));
318       }
319
320       aPosition.Translate (gp_Vec (aPosition.Direction().X() * aCylinderLength,
321                                    aPosition.Direction().Y() * aCylinderLength,
322                                    aPosition.Direction().Z() * aCylinderLength));
323       // Create a disk.
324       {
325         gp_Ax3  aSystem (aPosition.Location(), aPosition.Direction());
326         gp_Trsf aTrsf;
327         aTrsf.SetTransformation (aSystem, gp_Ax3());
328
329         anAxisGroup->AddPrimitiveArray (StdPrs_ToolDisk::Create (0.0, aConeDiametr, myNbFacettes, 1, aTrsf));
330       }
331
332       // Create a cone.
333       {
334         gp_Ax3  aSystem (aPosition.Location(), aPosition.Direction());
335         gp_Trsf aTrsf;
336         aTrsf.SetTransformation (aSystem, gp_Ax3());
337
338         anAxisGroup->AddPrimitiveArray (StdPrs_ToolCylinder::Create (aConeDiametr, 0.0, aConeLength, myNbFacettes, 1, aTrsf));
339       }
340     }
341   }
342
343   // Display labels.
344   {
345     Handle(Graphic3d_Group) aLabelGroup = myStructure->NewGroup();
346     const TCollection_ExtendedString aLabels[3] = { "X", "Y", "Z" };
347     const gp_Pnt aPoints[3] = { gp_Pnt (aScale + 2.0 * aRayon,                   0.0,               -aRayon),
348                                 gp_Pnt (               aRayon, aScale + 3.0 * aRayon,          2.0 * aRayon),
349                                 gp_Pnt (        -2.0 * aRayon,          0.5 * aRayon, aScale + 3.0 * aRayon) };
350     for (Standard_Integer anAxisIter = 0; anAxisIter < 3; ++anAxisIter)
351     {
352       Prs3d_Text::Draw (aLabelGroup, myTextAspect, aLabels[anAxisIter], aPoints[anAxisIter]);
353     }
354   }
355 }