0028010: Visualization, Prs3d_Arrow - add Shading presentation builder
[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_Arrow.hxx>
26 #include <Prs3d_LineAspect.hxx>
27 #include <Prs3d_ShadingAspect.hxx>
28 #include <Prs3d_Text.hxx>
29 #include <Prs3d_TextAspect.hxx>
30 #include <Prs3d_ToolSphere.hxx>
31 #include <V3d_View.hxx>
32
33 IMPLEMENT_STANDARD_RTTIEXT (V3d_Trihedron, Standard_Transient)
34
35 namespace
36 {
37   //! Compensates difference between old implementation (without transform persistence) and current implementation.
38   static const Standard_Real THE_INTERNAL_SCALE_FACTOR = 500.0;
39
40   static const Standard_ShortReal THE_CYLINDER_LENGTH      = 0.75f;
41   static const Standard_Integer   THE_CIRCLE_SERMENTS_NB   = 24;
42   static const Standard_Real      THE_CIRCLE_SEGMENT_ANGLE = 2.0 * M_PI / THE_CIRCLE_SERMENTS_NB;
43 }
44
45 //! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
46 class V3d_Trihedron::TrihedronStructure : public Graphic3d_Structure
47 {
48 public:
49   //! Main constructor.
50   TrihedronStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_Trihedron* theTrihedron)
51   : Graphic3d_Structure (theManager), myTrihedron (theTrihedron) {}
52
53   //! Override method to redirect to V3d_Trihedron.
54   virtual void Compute() Standard_OVERRIDE { myTrihedron->compute(); }
55
56 private:
57   V3d_Trihedron* myTrihedron;
58 };
59
60 // ============================================================================
61 // function : V3d_Trihedron
62 // purpose  :
63 // ============================================================================
64 V3d_Trihedron::V3d_Trihedron()
65 : myScale      (1.0),
66   myRatio      (0.8),
67   myDiameter   (0.05),
68   myNbFacettes (12),
69   myIsWireframe(Standard_False),
70   myToCompute  (Standard_True)
71 {
72   myTransformPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
73   SetPosition (Aspect_TOTP_LEFT_LOWER);
74
75   // Set material.
76   Graphic3d_MaterialAspect aShadingMaterial;
77   aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
78   aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
79
80   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
81   {
82     myArrowShadingAspects[anIt] = new Prs3d_ShadingAspect();
83     myArrowLineAspects[anIt]    = new Prs3d_LineAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0);
84
85     // mark texture map ON to actually disable environment map
86     myArrowShadingAspects[anIt]->Aspect()->SetTextureMapOn();
87     myArrowShadingAspects[anIt]->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
88     myArrowShadingAspects[anIt]->SetMaterial (aShadingMaterial);
89   }
90   myArrowShadingAspects[0]->SetColor (Quantity_NOC_RED);
91   myArrowLineAspects   [0]->SetColor (Quantity_NOC_RED);
92   myArrowShadingAspects[1]->SetColor (Quantity_NOC_GREEN);
93   myArrowLineAspects   [1]->SetColor (Quantity_NOC_GREEN);
94   myArrowShadingAspects[2]->SetColor (Quantity_NOC_BLUE1);
95   myArrowLineAspects   [2]->SetColor (Quantity_NOC_BLUE1);
96
97   mySphereShadingAspect = new Prs3d_ShadingAspect();
98   mySphereLineAspect    = new Prs3d_LineAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0);
99
100   // mark texture map ON to actually disable environment map
101   mySphereShadingAspect->Aspect()->SetTextureMapOn();
102   mySphereShadingAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
103   mySphereShadingAspect->SetMaterial (aShadingMaterial);
104   mySphereShadingAspect->SetColor (Quantity_NOC_WHITE);
105
106   myTextAspect = new Prs3d_TextAspect();
107   myTextAspect->SetFont ("Courier");
108   myTextAspect->SetHeight (16);
109   myTextAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT);
110   myTextAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
111 }
112
113 // ============================================================================
114 // function : SetLabelsColor
115 // purpose  :
116 // ============================================================================
117 void V3d_Trihedron::SetLabelsColor (const Quantity_Color& theColor)
118 {
119   myTextAspect->SetColor (theColor);
120 }
121
122 // ============================================================================
123 // function : SetArrowsColor
124 // purpose  :
125 // ============================================================================
126 void V3d_Trihedron::SetArrowsColor (const Quantity_Color& theXColor,
127                                     const Quantity_Color& theYColor,
128                                     const Quantity_Color& theZColor)
129 {
130   const Quantity_Color aColors[3] = { theXColor, theYColor, theZColor };
131   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
132   {
133     myArrowShadingAspects[anIt]->SetColor (aColors[anIt]);
134     myArrowLineAspects   [anIt]->SetColor (aColors[anIt]);
135   }
136 }
137
138 // ============================================================================
139 // function : SetScale
140 // purpose  :
141 // ============================================================================
142 void V3d_Trihedron::SetScale (const Standard_Real theScale)
143 {
144   if (Abs (myScale - theScale) > Precision::Confusion())
145   {
146     invalidate();
147   }
148   myScale = theScale;
149 }
150
151 // =======================================================================
152 // function : SetSizeRatio
153 // purpose  :
154 // =======================================================================
155 void V3d_Trihedron::SetSizeRatio (const Standard_Real theRatio)
156 {
157   if (Abs (myRatio - theRatio) > Precision::Confusion())
158   {
159     invalidate();
160   }
161   myRatio = theRatio;
162 }
163
164 // =======================================================================
165 // function : SetArrowDiameter
166 // purpose  :
167 // =======================================================================
168 void V3d_Trihedron::SetArrowDiameter (const Standard_Real theDiam)
169 {
170   if (Abs (myDiameter - theDiam) > Precision::Confusion())
171   {
172     invalidate();
173   }
174   myDiameter = theDiam;
175 }
176
177 // =======================================================================
178 // function : SetNbFacets
179 // purpose  :
180 // =======================================================================
181 void V3d_Trihedron::SetNbFacets (const Standard_Integer theNbFacets)
182 {
183   if (Abs (myNbFacettes - theNbFacets) > 0)
184   {
185     invalidate();
186   }
187   myNbFacettes = theNbFacets;
188 }
189
190 // ============================================================================
191 // function : Display
192 // purpose  :
193 // ============================================================================
194 void V3d_Trihedron::Display (const V3d_View& theView)
195 {
196   if (myStructure.IsNull())
197   {
198     myStructure = new TrihedronStructure (theView.Viewer()->StructureManager(), this);
199     myStructure->SetTransformPersistence (myTransformPers);
200     myStructure->SetZLayer (Graphic3d_ZLayerId_Topmost);
201     myStructure->SetDisplayPriority (9);
202     myStructure->SetInfiniteState (Standard_True);
203     myStructure->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
204     myStructure->CStructure()->ViewAffinity->SetVisible (Standard_False);
205     myStructure->CStructure()->ViewAffinity->SetVisible (theView.View()->Identification(), true);
206   }
207   if (myToCompute)
208   {
209     compute();
210   }
211
212   myStructure->Display();
213 }
214
215 // ============================================================================
216 // function : Erase
217 // purpose  :
218 // ============================================================================
219 void V3d_Trihedron::Erase()
220 {
221   if (!myStructure.IsNull())
222   {
223     myStructure->Erase();
224     myStructure.Nullify();
225   }
226 }
227
228 // ============================================================================
229 // function : SetPosition
230 // purpose  :
231 // ============================================================================
232 void V3d_Trihedron::SetPosition (const Aspect_TypeOfTriedronPosition thePosition)
233 {
234   Graphic3d_Vec2i anOffset (0, 0);
235   if ((thePosition & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
236   {
237     anOffset.x() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
238   }
239   if ((thePosition & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
240   {
241     anOffset.y() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
242   }
243
244   myTransformPers->SetCorner2d (thePosition);
245   myTransformPers->SetOffset2d (anOffset);
246 }
247
248 // ============================================================================
249 // function : compute
250 // purpose  :
251 // ============================================================================
252 void V3d_Trihedron::compute()
253 {
254   myStructure->GraphicClear (Standard_False);
255
256   // Create trihedron.
257   const Standard_Real aScale          = myScale * myRatio * THE_INTERNAL_SCALE_FACTOR;
258   const Standard_Real aCylinderLength = aScale * THE_CYLINDER_LENGTH;
259   const Standard_Real aCylinderRadius = aScale * myDiameter;
260   const Standard_Real aConeRadius     = myIsWireframe ? aCylinderRadius : (aCylinderRadius * 2.0);
261   const Standard_Real aConeLength     = aScale * (1.0 - THE_CYLINDER_LENGTH);
262   const Standard_Real aSphereRadius   = aCylinderRadius * 2.0;
263   const Standard_Real aRayon          = aScale / 30.0;
264   {
265     Handle(Graphic3d_Group) aSphereGroup = myStructure->NewGroup();
266
267     // Display origin.
268     if (myIsWireframe)
269     {
270       Handle(Graphic3d_ArrayOfPolylines) anCircleArray = new Graphic3d_ArrayOfPolylines (THE_CIRCLE_SERMENTS_NB + 2);
271       for (Standard_Integer anIt = THE_CIRCLE_SERMENTS_NB; anIt >= 0; --anIt)
272       {
273         anCircleArray->AddVertex (aRayon * Sin (anIt * THE_CIRCLE_SEGMENT_ANGLE),
274                                   aRayon * Cos (anIt * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
275       }
276       anCircleArray->AddVertex (aRayon * Sin (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE),
277                                 aRayon * Cos (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
278
279       aSphereGroup->SetGroupPrimitivesAspect (mySphereLineAspect->Aspect());
280       aSphereGroup->AddPrimitiveArray (anCircleArray);
281     }
282     else
283     {
284       gp_Trsf aSphereTransform;
285       aSphereGroup->SetGroupPrimitivesAspect (mySphereShadingAspect->Aspect());
286       aSphereGroup->AddPrimitiveArray (Prs3d_ToolSphere::Create (aSphereRadius, myNbFacettes, myNbFacettes, aSphereTransform));
287     }
288   }
289
290   // Display axes.
291   {
292     const gp_Ax1 anAxes[3] = { gp::OX(), gp::OY(), gp::OZ() };
293     for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
294     {
295       Handle(Graphic3d_Group) anAxisGroup = myStructure->NewGroup();
296       if (myIsWireframe)
297       {
298         // create a tube
299         Handle(Graphic3d_ArrayOfPrimitives) anArray = new Graphic3d_ArrayOfSegments (2);
300         anArray->AddVertex (0.0f, 0.0f, 0.0f);
301         anArray->AddVertex (anAxes[anIter].Direction().XYZ() * aCylinderLength);
302
303         anAxisGroup->SetGroupPrimitivesAspect (myArrowLineAspects[anIter]->Aspect());
304         anAxisGroup->AddPrimitiveArray (anArray);
305       }
306
307       Handle(Graphic3d_ArrayOfTriangles) aTriangles = Prs3d_Arrow::DrawShaded (anAxes[anIter],
308                                                                                myIsWireframe ? 0.0 : aCylinderRadius,
309                                                                                aCylinderLength + aConeLength,
310                                                                                aConeRadius,
311                                                                                aConeLength,
312                                                                                myNbFacettes);
313       anAxisGroup->SetGroupPrimitivesAspect (myArrowShadingAspects[anIter]->Aspect());
314       anAxisGroup->AddPrimitiveArray (aTriangles);
315     }
316   }
317
318   // Display labels.
319   {
320     Handle(Graphic3d_Group) aLabelGroup = myStructure->NewGroup();
321     const TCollection_ExtendedString aLabels[3] = { "X", "Y", "Z" };
322     const gp_Pnt aPoints[3] = { gp_Pnt (aScale + 2.0 * aRayon,                   0.0,               -aRayon),
323                                 gp_Pnt (               aRayon, aScale + 3.0 * aRayon,          2.0 * aRayon),
324                                 gp_Pnt (        -2.0 * aRayon,          0.5 * aRayon, aScale + 3.0 * aRayon) };
325     for (Standard_Integer anAxisIter = 0; anAxisIter < 3; ++anAxisIter)
326     {
327       Prs3d_Text::Draw (aLabelGroup, myTextAspect, aLabels[anAxisIter], aPoints[anAxisIter]);
328     }
329   }
330 }